+ push @to, $options{bcc} if defined($options{bcc});
+ # fully unpack all addresses found in @to (including Bcc) to make the
+ # envelope list
+ my @env_to;
+ foreach my $dest (@to) {
+ push @env_to, map { $_->address } Email::Address->parse($dest);
+ }
+
+ my $transport = email_sender_transport_or_error($domain);
+
+ my $error = '';
+ if ( ref($transport) ) {
+
+ local $SIG{__DIE__}; # don't want Mason __DIE__ handler active
+ local $@; # just in case
+ eval { sendmail($message, { transport => $transport,
+ from => $from,
+ to => \@env_to }) };
+
+ if (ref($@) and $@->isa('Email::Sender::Failure')) {
+ $error = $@->code.' ' if $@->code;
+ $error .= $@->message;
+ } else {
+ $error = $@;
+ }
+
+ } else {
+ $error = $transport;
+ }
+
+ # Logging
+ if ( $conf->exists('log_sent_mail') ) {
+ my $cust_msg = FS::cust_msg->new({
+ 'env_from' => $options{'from'},
+ 'env_to' => join(', ', @env_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'},
+ });
+ my $log_error = $cust_msg->insert;
+ warn "Error logging message: $log_error\n" if $log_error; # at least warn
+ }
+
+ $error;
+
+}
+
+sub email_sender_transport_or_error {
+ my $domain = shift;
+