OSDN Git Service

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