/usr/share/perl5/Jifty/Notification.pm is in libjifty-perl 1.10518+dfsg-1ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | use warnings;
use strict;
package Jifty::Notification;
use base qw/Jifty::Object Class::Accessor::Fast/;
use Email::Send ();
use Email::MIME::CreateHTML;
__PACKAGE__->mk_accessors(
qw/body html_body preface footer subject from _recipients _to_list to cc bcc/);
=head1 NAME
Jifty::Notification - Send emails from Jifty
=head1 USAGE
It is recommended that you subclass L<Jifty::Notification> and
override C<body>, C<html_body>, C<subject>, C<recipients>, and C<from>
for each message. (You may want a base class to provide C<from>,
C<preface> and C<footer> for example.) This lets you keep all of your
notifications in the same place.
However, if you really want to make a notification type in code
without subclassing, you can create a C<Jifty::Notification> and call
the C<set_body>, C<set_subject>, and so on methods on it.
=head1 METHODS
=cut
=head2 new [KEY1 => VAL1, ...]
Creates a new L<Jifty::Notification>. Any keyword args given are used
to call set accessors of the same name.
Then it calls C<setup>.
=cut
sub new {
my $class = shift;
my $self = bless {}, $class;
my %args = @_;
# initialize message bits to avoid 'undef' warnings
#for (qw(body preface footer subject)) { $self->$_(''); }
$self->_recipients( [] );
while ( my ( $arg, $value ) = each %args ) {
if ( $self->can($arg) ) {
$self->$arg($value);
} else {
$self->log->error(
( ref $self ) . " called with invalid argument $arg" );
}
}
$self->setup;
return $self;
}
=head2 setup
Your subclass should override this to set the various field values.
=cut
sub setup { }
=head2 send_one_message
Delivers the notification, using the L<Email::Send> mailer defined in
the C<Mailer> and C<MailerArgs> configuration arguments. Returns true
if mail was actually sent. Note errors are not the only cause of mail
not being sent -- for example, the recipients list could be empty.
If you wish to send HTML mail, set C<html_body>. If this is not set
(for backwards compatibility) a plain-text email is sent. If
C<html_body> and C<body> are both set, a multipart mail is sent. See
L<Email::MIME::CreateHTML> for how this is done.
Be aware that if you haven't set C<recipients>, this will fail
silently and return without doing anything useful.
=cut
sub send_one_message {
my $self = shift;
my @recipients = $self->recipients;
my $to = join( ', ',
map { ( ref $_ && $_->can('email') ? $_->email : $_ ) } grep {$_} @recipients );
$self->log->debug("Sending a ".ref($self)." to $to");
return unless ($to);
my $message = "";
my $appname = Jifty->config->framework('ApplicationName');
my %attrs = ( charset => 'UTF-8' );
my $from = Encode::encode(
'MIME-Header',
$self->from || _('%1 <%2>' , $appname, Jifty->config->framework('AdminEmail'))
);
my $subj = Encode::encode(
'MIME-Header',
$self->subject || _("A notification from %1!",$appname )
);
my $cc = Encode::encode('MIME-Header', $self->cc || '');
my $bcc = Encode::encode('MIME-Header', $self->bcc || '');
if ( defined $self->html_body ) {
# Email::MIME takes _bytes_, not characters, for the "body"
# argument, so we need to encode the full_body into UTF8.
# Modern Email::MIME->create takes a "body_str" argument which
# does the encoding for us, but Email::MIME::CreateHTML
# doesn't grok it. See also L</parts> for the other location
# which does the encode.
$message = Email::MIME->create_html(
header => [
From => $from,
To => $to,
Cc => $cc,
Bcc => $bcc,
Subject => $subj,
],
attributes => \%attrs,
text_body_attributes => \%attrs,
body_attributes => \%attrs,
text_body => Encode::encode_utf8( $self->full_body ),
body => Encode::encode_utf8( $self->full_html ),
embed => 0,
inline_css => 0,
);
# Since the containing messsage will still be us-ascii otherwise
$message->charset_set( $attrs{'charset'} );
} else {
$message = Email::MIME->create(
header => [
From => $from,
To => $to,
Cc => $cc,
Bcc => $bcc,
Subject => $subj,
],
attributes => \%attrs,
parts => $self->parts,
);
}
$message->encoding_set('8bit')
if ( scalar $message->parts == 1 );
$self->set_headers($message);
my $method = Jifty->config->framework('Mailer');
my $args_ref = Jifty->config->framework('MailerArgs');
$args_ref = [] unless defined $args_ref;
my $sender
= Email::Send->new( { mailer => $method, mailer_args => $args_ref } );
my $ret = $sender->send($message);
unless ($ret) {
$self->log->error("Error sending mail: $ret");
}
$ret;
}
=head2 set_headers MESSAGE
Takes a L<Email::MIME> object C<MESSAGE>, and modifies it as
necessary before sending it out. As the method name implies, this is
usually used to add or modify headers. By default, does nothing; this
method is meant to be overridden.
=cut
sub set_headers {}
=head2 body [BODY]
Gets or sets the body of the notification, as a string.
=head2 subject [SUBJECT]
Gets or sets the subject of the notification, as a string.
=head2 from [FROM]
Gets or sets the from address of the notification, as a string.
=head2 recipients [RECIPIENT, ...]
Gets or sets the addresses of the recipients of the notification, as a
list of strings (not a reference).
=cut
sub recipients {
my $self = shift;
$self->_recipients( [@_] ) if @_;
return @{ $self->_recipients };
}
=head2 email_from OBJECT
Returns the email address from the given object. This defaults to
calling an 'email' method on the object. This method will be called
by L</send> to get email addresses (for L</to>) out of the list of
L</recipients>.
=cut
sub email_from {
my $self = shift;
my ($obj) = @_;
if ( $obj->can('email') ) {
return $obj->email;
} else {
die "No 'email' method on " . ref($obj) . "; override 'email_from'";
}
}
=head2 to_list [OBJECT, OBJECT...]
Gets or sets the list of objects that the message will be sent to.
Each one is sent a separate copy of the email. If passed no
parameters, returns the objects that have been set. This also
suppresses duplicates.
=cut
sub to_list {
my $self = shift;
if (@_) {
my %ids = ();
$ids{ $self->to->id } = undef if $self->to;
$ids{ $_->id } = $_ for @_;
$self->_to_list( [ grep defined, values %ids ] );
}
return @{ $self->_to_list || [] };
}
=head2 send
Sends an individual email to every user in L</to_list>; it does this by
setting L</to> and L</recipient> to the first user in L</to_list>
calling L<Jifty::Notification>'s C<send> method, and progressing down
the list.
Additionally, if L</to> was set elsewhere, sends an email to that
person, as well.
=cut
sub send {
my $self = shift;
my $currentuser_object_class = Jifty->app_class("CurrentUser");
for my $to ( grep {defined} ($self->to, $self->to_list) ) {
if ($to->can('id')) {
next if $currentuser_object_class->can("nobody")
and $currentuser_object_class->nobody->id
and $to->id == $currentuser_object_class->nobody->id;
next if $to->id == $currentuser_object_class->superuser->id;
}
$self->to($to);
$self->recipients($to);
$self->send_one_message(@_);
}
}
=head2 to
Of the list of users that C<to> provided, returns the one which mail
is currently being sent to. This is set by the L</send> method, such
that it is available to all of the methods that
L<Jifty::Notification>'s C<send> method calls.
=cut
=head2 preface
Print a header for the message. You want to override this to print a message.
Returns the message as a scalar.
=cut
=head2 footer
Print a footer for the message. You want to override this to print a message.
Returns the message as a scalar.
=cut
=head2 full_body
The main, plain-text part of the message. This is the preface,
body, and footer joined by newlines.
=cut
sub full_body {
my $self = shift;
return join( "\n", grep { defined } $self->preface, $self->body, $self->footer );
}
=head2 full_html
Same as full_body, but with HTML.
=cut
sub full_html {
my $self = shift;
return join( "\n", grep { defined } $self->preface, $self->html_body, $self->footer );
}
=head2 parts
The parts of the message. You want to override this if you want to
send multi-part mail. By default, this method returns a single
part consisting of the result of calling C<< $self->full_body >>.
Returns the parts as an array reference.
=cut
sub parts {
my $self = shift;
# NOTICE: we should keep string in perl string (with utf8 flag)
# rather then encode it into octets. Email::MIME would call Encode::encode in
# its create function.
return [ Email::MIME->create(
attributes => { charset => 'UTF-8' },
body => Encode::encode_utf8( $self->full_body ),
) ];
}
=head2 magic_letme_token_for PATH
Returns a L<Jifty::LetMe> token which allows the current user to access a path on the
site.
=cut
sub magic_letme_token_for {
my $self = shift;
my $path = shift;
my %args = @_;
my $letme = Jifty::LetMe->new();
$letme->email( $self->to->email );
$letme->path($path);
$letme->args( \%args );
return ( $letme->as_url );
}
1;
|