invoice_email_pdf - Attach PDF invoice to emailed plain text invoices.
invoice_email_pdf_note - Replace plain text invoice with this note, when attaching a PDF.
'type' => 'textarea',
},
+ {
+ 'key' => 'invoice_email_pdf',
+ 'section' => 'billing',
+ 'description' => 'Send PDF invoice as an attachment to emailed invoices. By default, includes the plain text invoice as the email body, unless invoice_email_pdf_note is set.',
+ 'type' => 'checkbox'
+ },
+
+ {
+ 'key' => 'invoice_email_pdf_note',
+ 'section' => 'billing',
+ 'description' => 'If defined, this text will replace the default plain text invoice as the body of emailed PDF invoices.',
+ 'type' => 'textarea'
+ },
+
+
{
'key' => 'invoice_default_terms',
'section' => 'billing',
I<body> - (required) arrayref of body text lines
+I<mimeparts> - (optional) arrayref of MIME::Entity->build PARAMHASH refs, not MIME::Entity objects. These will be passed as arguments to MIME::Entity->attach().
+
=cut
use vars qw( $conf );
use Date::Format;
use Mail::Header;
use Mail::Internet 1.44;
+use MIME::Entity;
use FS::UID;
FS::UID->install_callback( sub {
$ENV{MAILADDRESS} = $options{'from'};
my $to = ref($options{to}) ? join(', ', @{ $options{to} } ) : $options{to};
- my @header = (
- 'From: '. $options{'from'},
- 'To: '. $to,
- 'Sender: '. $options{'from'},
- 'Reply-To: '. $options{'from'},
- 'Date: '. time2str("%a, %d %b %Y %X %z", time),
- 'Subject: '. $options{'subject'},
- );
- push @header, 'Content-Type: '. $options{'content-type'}
- if exists($options{'content-type'});
- my $header = new Mail::Header ( \@header );
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => $options{'body'},
+ my @mimeparts = (ref($options{'mimeparts'}) eq 'ARRAY')
+ ? @{$options{'mimeparts'}} : ();
+ my $mimetype = (scalar(@mimeparts)) ? 'multipart/mixed' : 'text/plain';
+
+ my @mimeargs;
+ if (scalar(@mimeparts)) {
+ @mimeargs = (
+ 'Type' => 'multipart/mixed',
+ );
+
+ push @mimeparts,
+ {
+ 'Data' => $options{'body'},
+ 'Disposition' => 'inline',
+ 'Type' => (($options{'content-type'} ne '')
+ ? $options{'content-type'} : 'text/plain'),
+ };
+ } else {
+ @mimeargs = (
+ 'Type' => (($options{'content-type'} ne '')
+ ? $options{'content-type'} : 'text/plain'),
+ 'Data' => $options{'body'},
+ );
+ }
+
+ my $message = MIME::Entity->build(
+ 'From' => $options{'from'},
+ 'To' => $to,
+ 'Sender' => $options{'from'},
+ 'Reply-To' => $options{'from'},
+ 'Date' => time2str("%a, %d %b %Y %X %z", time),
+ 'Subject' => $options{'subject'},
+ @mimeargs,
);
+ foreach my $part (@mimeparts) {
+ next unless ref($part) eq 'HASH'; #warn?
+ $message->attach(%$part);
+ }
+
my $smtpmachine = $conf->config('smtpmachine');
$!=0;
# Send it
+ #warn "Headers: \n" . join('',@{$hdr->header});
+ #warn "Body: \n" . join('',@{$src->body});
+
my $ok = $smtp->mail( $envelope ) &&
$smtp->to(@addr) &&
$smtp->data(join("", @{$hdr->header},"\n",@{$src->body}));
$balance;
}
+
+=item generate_email PARAMHASH
+
+PARAMHASH can contain the following:
+
+=over 4
+
+=item from => sender address, required
+
+=item tempate => alternate template name, optional
+
+=item print_text => text attachment arrayref, optional
+
+=item subject => email subject, optional
+
+=back
+
+Returns an argument list to be passed to L<FS::cust_bill::send>.
+
+=cut
+
+sub generate_email {
+
+ my $self = shift;
+ my %args = @_;
+
+ my $mimeparts;
+ if ($conf->exists('invoice_email_pdf')) {
+ #warn "[FS::cust_bill::send] creating PDF attachment";
+ #mime parts arguments a la MIME::Entity->build().
+ $mimeparts = [
+ {
+ 'Type' => 'application/pdf',
+ 'Encoding' => 'base64',
+ 'Data' => [ $self->print_pdf('', $args{'template'}) ],
+ 'Disposition' => 'attachment',
+ 'Filename' => 'invoice.pdf',
+ },
+ ];
+ }
+
+ my $email_text;
+ if ($conf->exists('invoice_email_pdf')
+ and scalar($conf->config('invoice_email_pdf_note'))) {
+
+ #warn "[FS::cust_bill::send] using 'invoice_email_pdf_note'";
+ $email_text = [ map { $_ . "\n" } $conf->config('invoice_email_pdf_note') ];
+ } else {
+ #warn "[FS::cust_bill::send] not using 'invoice_email_pdf_note'";
+ if (ref($args{'print_text'}) eq 'ARRAY') {
+ $email_text = $args{'print_text'};
+ } else {
+ $email_text = [ $self->print_text('', $args{'template'}) ];
+ }
+ }
+
+ my @invoicing_list;
+ if (ref($args{'to'} eq 'ARRAY')) {
+ @invoicing_list = @{$args{'to'}};
+ } else {
+ @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list;
+ }
+
+ return (
+ 'from' => $args{'from'},
+ 'to' => [ @invoicing_list ],
+ 'subject' => (($args{'subject'}) ? $args{'subject'} : 'Invoice'),
+ 'body' => $email_text,
+ 'mimeparts' => $mimeparts,
+ );
+
+
+}
+
=item send [ TEMPLATENAME [ , AGENTNUM [ , INVOICE_FROM ] ] ]
Sends this invoice to the destinations configured for this customer: send
@invoicing_list = ($invoice_from) unless @invoicing_list;
my $error = send_email(
- 'from' => $invoice_from,
- 'to' => [ grep { $_ ne 'POST' } @invoicing_list ],
- 'subject' => 'Invoice',
- 'body' => \@print_text,
+ $self->generate_email(
+ 'from' => $invoice_from,
+ 'to' => [ grep { $_ ne 'POST' } @invoicing_list ],
+ 'print_text' => [ @print_text ],
+ )
);
die "can't email invoice: $error\n" if $error;
#die "$error\n" if $error;
<li><a href="http://search.cpan.org/dist/Spreadsheet-WriteExcel">Spreadsheet::WriteExcel</a>
<li><a href="http://search.cpan.org/dist/IO-stringy">IO-stringy (IO::Scalar)</a>
<li><a href="http://search.cpan.org/dist/Frontier-RPC">Frontier::RPC (Frontier::RPC2)</a>
+ <li><a href="http://search.cpan.org/search?mode=module&query=MIME::Entity">MIME::Entity (MIME-tools)</a>
<!-- <li><a href="http://search.cpan.org/dist/Crypt-YAPassGen">Crypt::YAPassGen</a> -->
<li><a href="http://search.cpan.org/dist/ApacheDBI">Apache::DBI</a> <i>(optional but recommended for better webinterface performance)</i>
</ul>
die "Can't find invoice!\n" unless $cust_bill;
my $error = send_email(
- 'from' => $cust_bill->_agent_invoice_from || $conf->config('invoice_from'),
- 'to' => [ grep { $_ ne 'POST' } $cust_bill->cust_main->invoicing_list ],
- 'subject' => 'Invoice',
- 'body' => [ $cust_bill->print_text ],
+ $cust_bill->generate_email(
+ 'from' => $cust_bill->_agent_invoice_from || $conf->config('invoice_from'),
+ )
);
eidiot($error) if $error;