俺Pla
いろんなとこからコピペしてPublish::Plamailとかでっちあげてみた。
package Plagger::Plugin::Publish::Plamail; use strict; use base qw( Plagger::Plugin ); use DateTime; use DateTime::Format::Mail; use Encode; use Encode::MIME::Header; use HTML::Entities; use HTML::Parser; use Jcode; use MIME::Lite; our %TLSConn; sub rule_hook { 'publish.feed' } sub register { my($self, $context) = @_; $context->register_hook( $self, 'publish.init' => \&initialize, 'publish.feed' => \¬ify, ); } sub init { my $self = shift; $self->SUPER::init(@_); $self->conf->{mailto} or Plagger->context->error("mailto is required"); $self->conf->{mailfrom} ||= 'plagger@localhost'; } sub initialize { my($self,$context) = @_; # authenticate POP before SMTP if (my $conf = $self->conf->{pop3}) { require Net::POP3; my $pop = Net::POP3->new($conf->{host}); if ($pop->apop($conf->{username}, $conf->{password})) { $context->log(info => 'APOP login succeed'); } elsif ($pop->login($conf->{username}, $conf->{password})) { $context->log(info => 'POP3 login succeed'); } else { $context->log(error => 'POP3 login error'); } $pop->quit; } } sub notify { my($self, $context, $args) = @_; return if $args->{feed}->count == 0; my $feed = $args->{feed}; my $subject = $feed->title || '(no-title)'; my @enclosure_cb; if ($self->conf->{attach_enclosures}) { for my $entry ($args->{feed}->entries) { push @enclosure_cb, $self->prepare_enclosures($entry); } } my $body = $self->templatize('plamail_notify.tt', { feed => $feed }); my $cfg = $self->conf; $context->log(info => "Sending $subject to $cfg->{mailto}"); my $feed_title = $feed->title; $feed_title =~ tr/,//d; my $now = Plagger::Date->now(timezone => $context->conf->{timezone}); my $msg = MIME::Lite->new( Date => $now->format('Mail'), From => encode('MIME-Header-ISO_2022_JP', qq("$feed_title" <$cfg->{mailfrom}>)), To => $cfg->{mailto}, Subject => encode('MIME-Header-ISO_2022_JP', $subject), Type => 'text/plain; charset=iso-2022-jp', Encoding=> '7bit', Data => encode_body($args->{entry}->body), ); $msg->replace("X-Mailer" => "Plagger/$Plagger::VERSION"); # $msg->attach( # Type => 'text/html; charset=utf-8',#'text/html; charset=utf-8' # Data => encode("utf-8", $body),#("utf-8", $body) # Encoding => 'quoted-printable', # ); for my $cb (@enclosure_cb) { $cb->($msg); } my $route = $cfg->{mailroute} || { via => 'smtp', host => 'localhost' }; $route->{via} ||= 'smtp'; eval { if ($route->{via} eq 'smtp_tls') { $self->{tls_args} = [ $route->{host}, User => $route->{username}, Password => $route->{password}, Port => $route->{port} || 587, ]; $msg->send_by_smtp_tls(@{ $self->{tls_args} }); } elsif ($route->{via} eq 'sendmail') { my %param = (FromSender => "<$cfg->{mailfrom}>"); $param{Sendmail} = $route->{command} if defined $route->{command}; $msg->send('sendmail', %param); } else { my @args = $route->{host} ? ($route->{host}) : (); $msg->send($route->{via}, @args); } }; if ($@) { $context->log(error => "Error while sending emails: $@"); } } sub encode_body { my $str = shift; $str = remove_utf8_flag($str); $str =~ s/\x0D\x0A/\n/g; $str =~ tr/\r/\n/; return Jcode->new($str, guess_encoding($str))->jis; } sub guess_encoding { my $str = shift; my $enc = Jcode::getcode($str) || 'euc'; $enc = 'euc' if $enc eq 'ascii' || $enc eq 'binary'; return $enc; } sub remove_utf8_flag { pack 'C0A*', $_[0] } sub prepare_enclosures { my($self, $entry) = @_; if (grep $_->is_inline, $entry->enclosures) { # replace inline enclosures to cid: entities my %url2enclosure = map { $_->url => $_ } $entry->enclosures; my $output; my $p = HTML::Parser->new(api_version => 3); $p->handler( default => sub { $output .= $_[0] }, "text" ); $p->handler( start => sub { my($tag, $attr, $attrseq, $text) = @_; # TODO: use HTML::Tagset? if (my $url = $attr->{src}) { if (my $enclosure = $url2enclosure{$url}) { $attr->{src} = "cid:" . $self->enclosure_id($enclosure); } $output .= $self->generate_tag($tag, $attr, $attrseq); } else { $output .= $text; } }, "tag, attr, attrseq, text"); $p->parse($entry->body); $p->eof; $entry->body($output); } return sub { my $msg = shift; for my $enclosure (grep $_->local_path, $entry->enclosures) { my %param = ( Type => $enclosure->type, Path => $enclosure->local_path, Filename => $enclosure->filename, ); if ($enclosure->is_inline) { $param{Id} = '<' . $self->enclosure_id($enclosure) . '>'; $param{Disposition} = 'inline'; } else { $param{Disposition} = 'attachment'; } $msg->attach(%param); } } } sub generate_tag { my($self, $tag, $attr, $attrseq) = @_; return "<$tag " . join(' ', map { $_ eq '/' ? '/' : sprintf qq(%s="%s"), $_, encode_entities($attr->{$_}, q(<>"')) } @$attrseq) . '>'; } sub enclosure_id { my($self, $enclosure) = @_; return Digest::MD5::md5_hex($enclosure->url->as_string) . '@Plagger'; } sub DESTORY { my $self = shift; return unless $self->{tls_args}; my $conn_key = join "|", @{ $self->{tls_args} }; eval { local $SIG{__WARN__} = sub { }; $TLSConn{$conn_key} && $TLSConn{$conn_key}->quit; }; 1;
Can't call method "body" on an undefined value
とか出て動かねえよばーかばーか。
ぐすん。