use IPC::Run3; # for do_print... should just use IPC::Run i guess
use File::Temp;
use Tie::IxHash;
+use Encode;
#do NOT depend on any FS:: modules here, causes weird (sometimes unreproducable
#until on client machine) dependancy loops. put them in FS::Misc::Something
#instead
(optional) type parameter for multipart/related messages
-=item cust_msg
+=item custnum
-(optional) L<FS::cust_msg> object. If provided, it will be updated
-with the message envelope information, contents, and server response.
+(optional) L<FS::cust_main> key; if passed, the message will be logged
+(if logging is enabled) with this custnum.
+
+=item msgnum
+
+(optional) L<FS::msg_template> key, for logging.
=back
use MIME::Entity;
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP;
-use Email::Sender::Transport::SMTP::TLS;
+use Email::Sender::Transport::SMTP::TLS 0.11;
use FS::UID;
FS::UID->install_callback( sub {
unshift @mimeparts, {
'Type' => ( $options{'content-type'} || 'text/plain' ),
+ 'Charset' => 'UTF-8',
'Data' => $options{'body'},
'Encoding' => ( $options{'content-type'} ? '-SUGGEST' : '7bit' ),
'Disposition' => 'inline',
'Type' => ( $options{'content-type'} || 'text/plain' ),
'Data' => $options{'body'},
'Encoding' => ( $options{'content-type'} ? '-SUGGEST' : '7bit' ),
+ 'Charset' => 'UTF-8',
);
}
}
+ my $from = $options{from};
+ $from =~ s/^\s*//; $from =~ s/\s*$//;
+ if ( $from =~ /^(.*)\s*<(.*@.*)>$/ ) {
+ # a common idiom
+ $from = $2;
+ }
+
my $domain;
- if ( $options{'from'} =~ /\@([\w\.\-]+)/ ) {
+ if ( $from =~ /\@([\w\.\-]+)/ ) {
$domain = $1;
} else {
warn 'no domain found in invoice from address '. $options{'from'}.
'Sender' => $options{'from'},
'Reply-To' => $options{'from'},
'Date' => time2str("%a, %d %b %Y %X %z", $time),
- 'Subject' => $options{'subject'},
+ 'Subject' => Encode::encode('MIME-Header', $options{'subject'}),
'Message-ID' => "<$message_id>",
@mimeargs,
);
push @to, $options{bcc} if defined($options{bcc});
local $@; # just in case
eval { sendmail($message, { transport => $transport,
- from => $options{from},
+ from => $from,
to => \@to }) };
my $error = '';
}
# Logging
- my $cust_msg = $options{'cust_msg'};
- if ( $cust_msg ) {
- $cust_msg->env_from($options{from});
- $cust_msg->env_to(join(",", @to));
- $cust_msg->header($message->header_as_string);
- $cust_msg->body($message->body_as_string);
- $cust_msg->_date($time);
- $cust_msg->error($error);
- $cust_msg->status( $error ? 'failed' : 'sent' );
- $cust_msg->replace;
- };
- return $error;
+ if ( $conf->exists('log_sent_mail') ) {
+ my $cust_msg = FS::cust_msg->new({
+ 'env_from' => $options{'from'},
+ 'env_to' => join(', ', @to),
+ 'header' => $message->header_as_string,
+ 'body' => $message->body_as_string,
+ '_date' => $time,
+ 'error' => $error,
+ 'custnum' => $options{'custnum'},
+ 'msgnum' => $options{'msgnum'},
+ 'status' => ($error ? 'failed' : 'sent'),
+ 'msgtype' => $options{'msgtype'},
+ });
+ $cust_msg->insert; # ignore errors
+ }
+ $error;
}
Email body (Text alternative). Arrayref of lines, or scalar.
-=item cust_msg (optional)
+=item custnum, msgnum (optional)
-An L<FS::cust_msg> object. Will be passed through to send_email.
+Customer and template numbers, passed through to send_email for logging.
=back
my $me = '[FS::Misc::generate_email]';
- my %return = (
- 'from' => $args{'from'},
- 'to' => $args{'to'},
- 'bcc' => $args{'bcc'},
- 'subject' => $args{'subject'},
- 'cust_msg'=> $args{'cust_msg'},
- );
-
- #if (ref($args{'to'}) eq 'ARRAY') {
- # $return{'to'} = $args{'to'};
- #} else {
- # $return{'to'} = [ grep { $_ !~ /^(POST|FAX)$/ }
- # $self->cust_main->invoicing_list
- # ];
- #}
+ my @fields = qw(from to bcc subject custnum msgnum msgtype);
+ my %return;
+ @return{@fields} = @args{@fields};
warn "$me creating HTML/text multipart message"
if $DEBUG;
$alternative->attach(
'Type' => 'text/plain',
- #'Encoding' => 'quoted-printable',
- 'Encoding' => '7bit',
+ 'Encoding' => 'quoted-printable',
+ 'Charset' => 'UTF-8',
+ #'Encoding' => '7bit',
'Data' => $data,
'Disposition' => 'inline',
);
' '. encode_entities($return{'subject'}),
' </title>',
' </head>',
- ' <body bgcolor="#e8e8e8">',
+ ' <body bgcolor="#ffffff">',
@html_data,
' </body>',
'</html>',
'';
}
+=item process_send_generated_email OPTION => VALUE ...
+
+Takes arguments as per send_email() and sends the message. This
+will die on any error and can be used in the job queue.
+
+=cut
+
+sub process_send_generated_email {
+ my %args = @_;
+ my $error = send_email(%args);
+ die "$error\n" if $error;
+ '';
+}
+
=item send_fax OPTION => VALUE ...
Options:
open(POSTSCRIPT, "<$file.ps")
or die "can't open $file.ps: $! (error in LaTeX template?)\n";
- unlink("$file.dvi", "$file.log", "$file.aux", "$file.ps", "$file.tex");
+ unlink("$file.dvi", "$file.log", "$file.aux", "$file.ps", "$file.tex")
+ unless $FS::CurrentUser::CurrentUser->option('save_tmp_typesetting');
my $ps = '';
open(PDF, "<$file.pdf")
or die "can't open $file.pdf: $! (error in LaTeX template?)\n";
- unlink("$file.dvi", "$file.log", "$file.aux", "$file.pdf", "$file.tex");
+ unlink("$file.dvi", "$file.log", "$file.aux", "$file.pdf", "$file.tex")
+ unless $FS::CurrentUser::CurrentUser->option('save_tmp_typesetting');
my $pdf = '';
while (<PDF>) {
}
-=item print ARRAYREF
+=item do_print ARRAYREF [, OPTION => VALUE ... ]
Sends the lines in ARRAYREF to the printer.
+Options available are:
+
+=over 4
+
+=item agentnum
+
+Uses this agent's 'lpr' configuration setting override instead of the global
+value.
+
+=item lpr
+
+Uses this command instead of the configured lpr command (overrides both the
+global value and agentnum).
+
=cut
sub do_print {
- my $data = shift;
+ my( $data, %opt ) = @_;
- my $lpr = $conf->config('lpr');
+ my $lpr = ( exists($opt{'lpr'}) && $opt{'lpr'} )
+ ? $opt{'lpr'}
+ : $conf->config('lpr', $opt{'agentnum'} );
my $outerr = '';
run3 $lpr, $data, \$outerr, \$outerr;