OSDN Git Service

Plugin::Sendmail: add _encode_header()
[newslash/newslash.git] / src / newslash_web / lib / Newslash / Plugin / Sendmail.pm
1 package Newslash::Plugin::Sendmail;
2 use Mojo::Base 'Mojolicious::Plugin';
3 use Email::Valid;
4 use Email::Simple;
5 use Email::Sender::Simple;
6 use Email::Sender::Transport::SMTP;
7 use Encode;
8 use Data::Dumper;
9
10 has 'last_error';
11 has 'app';
12
13 sub register {
14     my ($self, $app, $conf) = @_;
15     $self->app($app);
16     $app->helper(sendmail => sub { shift; $self->sendmail(@_); });
17
18     # default config values
19     my $cnf = $app->config->{Sendmail} ||= {};
20
21     $cnf->{default_from} ||= 'admin@example.com';
22     $cnf->{smtp_host} ||= 'example.com';
23     $cnf->{smtp_port} ||= '25';
24 }
25
26 sub _encode_header {
27     my ($self, $text) = @_;
28     my $encoded = encode('MIME-Header-ISO_2022_JP', $text);
29     $encoded =~ s/\n//g;
30     return $encoded;
31 }
32
33 sub _send {
34     my ($self, $from, $to, $title, $body) = @_;
35
36     # create header and body
37     my $header = [
38                   From    => $self->_encode_header($from),
39                   To      => $self->_encode_header($to),
40                   Subject => $self->_encode_header($title),
41                   'Content-Type' => 'text/plain; charset=ISO-2022-JP',
42                   'Content-Transfer-Encoding' => '7bit',
43                  ];
44
45     my $encoded_body = encode('iso-2022-jp', $body);
46
47     # create message
48     my $email = Email::Simple->create(header => $header,
49                                       body => $encoded_body);
50
51     # create transport
52     my $smtp_host = $self->app->config->{Sendmail}->{smtp_host};
53     my $smtp_port = $self->app->config->{Sendmail}->{smtp_port};
54     my $smtp_timeout = $self->app->config->{Sendmail}->{smtp_timeout};
55     my $transport = Email::Sender::Transport::SMTP->new({ host => $smtp_host,
56                                                           port => $smtp_port,
57                                                           timeout => $smtp_timeout,
58                                                         });
59
60     # send message
61     my $rs = eval { Email::Sender::Simple->send($email, {transport => $transport}) };
62     if (!$rs) {
63         my ($msg, $code) = ($@->message, $@->code);
64         $self->app->log->error("Sendmail: sendmail error. $msg ($code)");
65         return;
66     }
67     return 1;
68 }
69
70 sub _render {
71     my ($self, $template_name, $vars, $opts) = @_;
72     $opts ||= {};
73
74     my $renderer = $self->app->tt2renderer;
75     my $rs = $renderer->render($template_name, $vars);
76
77     my ($title, $body) = split(/\n/, $rs, 2);
78     $body =~ s/\A\n+//;
79     return ($title, $body);
80 }
81
82 sub sendmail {
83     my $self = shift;
84     my $args = {@_};
85
86     if (!defined $args->{to}) {
87         $self->app->log->error("Sendmail: no recipient given!");
88         return;
89     }
90
91     my $to_address;
92     my $recipient_user;
93
94     # check recipient
95     if (ref($args->{to}) eq "HASH") {
96         $recipient_user = $args->{to};
97     }
98     elsif (ref($args->{to}) eq "ARRAY") {
99         # TODO
100     }
101     elsif (ref($args->{to}) eq "") {
102         if ($args->{to} =~ m/^\d+$/) {
103             # uid is given
104             $recipient_user = $self->app->model('users')->select(uid => $args->{to});
105         }
106         else {
107             my $encoded_to = encode('MIME-Header-ISO_2022_JP', $args->{to});
108             if (Email::Valid->address($encoded_to)) {
109                 $to_address = $args->{to};
110             }
111         }
112     }
113
114     if ($recipient_user) {
115         $to_address = $recipient_user->{realemail};
116     }
117
118     if (!$to_address) {
119         $self->app->log->error("Sendmail: invalid recipient: $args->{to}");
120         return;
121     }
122
123
124     # check from address
125     my $from_address = $args->{from} || $self->app->config->{Sendmail}->{default_from};
126
127     # create title and body
128     my $title = $args->{title};
129     my $body = $args->{body};
130
131     if ($args->{template}) {
132         # render template
133         ($title, $body) = eval { $self->_render($args->{template},
134                                                    $args->{params}); };
135         if (!$title) {
136             $self->app->log->error("Sendmail: template error: $@");
137             return;
138         }
139     }
140
141     if (!$title) {
142         $self->app->log->error("Sendmail: no title given. to: $to_address");
143         return;
144     }
145
146     if (!$body) {
147         $self->app->log->error("Sendmail: no body given. title: $title, to: $to_address");
148         return;
149     }
150
151     # if render only mode, return items.
152     if ($args->{render_only}) {
153         return wantarray ? ($from_address, $to_address, $title, $body) : { from => $from_address,
154                                                                              to => $to_address,
155                                                                              title => $title,
156                                                                              body => $body };
157     }
158
159     # send
160     my $rs = $self->_send($from_address, $to_address, $title, $body);
161
162     if (!$rs) {
163         $self->app->log->error("Sendmail: fail to send mail. title: $title, to: $to_address");
164         return;
165     }
166
167     return 1;
168 }
169
170 1;
171
172 =encoding utf8
173
174 =head1 NAME
175
176 Newslash::Plugin::Sendmail - Newslash sendmail plugin
177
178 =head1 SYNOPSIS
179
180   # Mojolicious
181   $app->plugin('Newslash::Plugin::Sendmail');
182
183 =head1 DESCRIPTION
184
185 L<Newslash::Plugin::Sendmail> implements mail related tasks.
186
187
188 =head1 HELPERS
189
190 L<Mojolicious::Plugin::Sendmail> implements the following helpers.
191
192 =head2 boxes
193
194   [% helpers.boxes() %]
195
196 Fetch box contents for current user and returns them.
197
198 =head2 format_timestamp
199
200   $c->format_timestamp(user => $user, epoch => $epoch, format => "user")
201   $c->format_timestamp(datetime => $dt, format => "simple")
202
203 Return formated string.
204
205 =head1 METHODS
206
207 =head2 register
208
209   $plugin->register(Mojolicious->new);
210
211 Register helpers in L<Mojolicious> application.
212
213 head2 sendmail
214
215   $app->sendmail(to => $user,
216                  template => "message/initial_password",
217                  params => $render_params);
218
219 Render template with params and send mail.
220
221 =head1 SEE ALSO
222
223 L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicious.org>.
224
225 =cut