- Support SMTP Delivery Status Notifications - RFC3461 (#1486142)

release-0.6
alecpl 15 years ago
parent 9db4ca92ef
commit f22ea7ba18

@ -21,6 +21,7 @@ CHANGELOG Roundcube Webmail
- Add unique index on users.username+users.mail_host
- Make htmleditor option more consistent and add option to use HTML on reply to HTML message (#1485840)
- Use empty envelope sender address for message disposition notifications (RFC2298.3)
- Support SMTP Delivery Status Notifications - RFC3461 (#1486142)
RELEASE 0.4.2
-------------

@ -334,12 +334,6 @@ $rcmail_config['protect_default_folders'] = true;
// if in your system 0 quota means no limit set this option to true
$rcmail_config['quota_zero_as_unlimited'] = false;
// Behavior if a received message requests a message delivery notification (read receipt)
// 0 = ask the user, 1 = send automatically, 2 = ignore (never send or ask)
// 3 = send automatically if sender is in addressbook, otherwise ask the user
// 4 = send automatically if sender is in addressbook, otherwise ignore
$rcmail_config['mdn_requests'] = 0;
// Make use of the built-in spell checker. It is based on GoogieSpell.
// Since Google only accepts connections over https your PHP installatation
// requires to be compiled with Open SSL support
@ -571,5 +565,16 @@ $rcmail_config['search_mods'] = null; // Example: array('*' => array('subject'=
// when user is over quota and Trash is included in the quota.
$rcmail_config['delete_always'] = false;
// end of config file
// Behavior if a received message requests a message delivery notification (read receipt)
// 0 = ask the user, 1 = send automatically, 2 = ignore (never send or ask)
// 3 = send automatically if sender is in addressbook, otherwise ask the user
// 4 = send automatically if sender is in addressbook, otherwise ignore
$rcmail_config['mdn_requests'] = 0;
// Return receipt checkbox default state
$rcmail_config['mdn_default'] = 0;
// Delivery Status Notification checkbox default state
$rcmail_config['dsn_default'] = 0;
// end of config file

@ -399,9 +399,9 @@ class rcube_message
if ($part_orig_mimetype == 'message/rfc822' && !empty($mail_part->filename))
$this->attachments[] = $mail_part;
}
// part text/[plain|html] OR message/delivery-status
// part text/[plain|html] or delivery status
else if ((($part_mimetype == 'text/plain' || $part_mimetype == 'text/html') && $mail_part->disposition != 'attachment') ||
$part_mimetype == 'message/delivery-status' || $part_mimetype == 'message/disposition-notification'
in_array($part_mimetype, array('message/delivery-status', 'text/rfc822-headers', 'message/disposition-notification'))
) {
// Allow plugins to handle also this part
$plugin = $this->app->plugins->exec_hook('message_part_structure',

@ -153,17 +153,16 @@ class rcube_smtp
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param mixed The message headers to send with the mail
* Either as an associative array or a finally
* formatted string
*
* @param mixed The full text of the message body, including any Mime parts
* or file handle
* @param array Delivery options (e.g. DSN request)
*
* @return bool Returns true on success, or false on error
*/
public function send_mail($from, $recipients, &$headers, &$body)
public function send_mail($from, $recipients, &$headers, &$body, $opts=null)
{
if (!is_object($this->conn))
return false;
@ -183,7 +182,7 @@ class rcube_smtp
else
{
$this->reset();
$this->response[] .= "Invalid message headers";
$this->response[] = "Invalid message headers";
return false;
}
@ -191,10 +190,24 @@ class rcube_smtp
if (!isset($from))
{
$this->reset();
$this->response[] .= "No From address has been provided";
$this->response[] = "No From address has been provided";
return false;
}
// RFC3461: Delivery Status Notification
if ($opts['dsn']) {
$exts = $this->conn->getServiceExtensions();
if (!isset($exts['DSN'])) {
$this->error = array('label' => 'smtpdsnerror');
$this->response[] = "DSN not supported";
return false;
}
$from_params = 'RET=HDRS';
$recipient_params = 'NOTIFY=SUCCESS,FAILURE';
}
// RFC2298.3: remove envelope sender address
if (preg_match('/Content-Type: multipart\/report/', $text_headers)
&& preg_match('/report-type=disposition-notification/', $text_headers)
@ -203,12 +216,12 @@ class rcube_smtp
}
// set From: address
if (PEAR::isError($this->conn->mailFrom($from)))
if (PEAR::isError($this->conn->mailFrom($from, $from_params)))
{
$err = $this->conn->getResponse();
$this->error = array('label' => 'smtpfromerror', 'vars' => array(
'from' => $from, 'code' => $this->conn->_code, 'msg' => $err[1]));
$this->response[] .= "Failed to set sender '$from'";
$this->response[] = "Failed to set sender '$from'";
$this->reset();
return false;
}
@ -225,11 +238,11 @@ class rcube_smtp
// set mail recipients
foreach ($recipients as $recipient)
{
if (PEAR::isError($this->conn->rcptTo($recipient))) {
if (PEAR::isError($this->conn->rcptTo($recipient, $recipient_params))) {
$err = $this->conn->getResponse();
$this->error = array('label' => 'smtptoerror', 'vars' => array(
'to' => $recipient, 'code' => $this->conn->_code, 'msg' => $err[1]));
$this->response[] .= "Failed to add recipient '$recipient'";
$this->response[] = "Failed to add recipient '$recipient'";
$this->reset();
return false;
}
@ -261,7 +274,7 @@ class rcube_smtp
$msg = $result->getMessage();
$this->error = array('label' => 'smtperror', 'vars' => array('msg' => $msg));
$this->response[] .= "Failed to send data";
$this->response[] = "Failed to send data";
$this->reset();
return false;
}

@ -209,6 +209,7 @@ $labels['addattachment'] = 'Attach a file';
$labels['charset'] = 'Charset';
$labels['editortype'] = 'Editor type';
$labels['returnreceipt'] = 'Return receipt';
$labels['dsn'] = 'Delivery status notification';
$labels['editidents'] = 'Edit identities';
$labels['checkspelling'] = 'Check spelling';
@ -374,6 +375,7 @@ $labels['insertsignature'] = 'Insert signature';
$labels['previewpanemarkread'] = 'Mark previewed messages as read';
$labels['afternseconds'] = 'after $n seconds';
$labels['reqmdn'] = 'Always request a return receipt';
$labels['reqdsn'] = 'Always request a delivery status notification';
$labels['folder'] = 'Folder';
$labels['folders'] = 'Folders';

@ -109,6 +109,7 @@ $messages['smtpautherror'] = 'SMTP Error ($code): Authentication failed';
$messages['smtpfromerror'] = 'SMTP Error ($code): Failed to set sender "$from" ($msg)';
$messages['smtptoerror'] = 'SMTP Error ($code): Failed to add recipient "$to" ($msg)';
$messages['smtprecipientserror'] = 'SMTP Error: Unable to parse recipients list';
$messages['smtpdsnerror'] = 'SMTP Error: No support for Delivery Status Notifications';
$messages['smtperror'] = 'SMTP Error: $msg';
$messages['emailformaterror'] = 'Invalid e-mail address: $email';
$messages['toomanyrecipients'] = 'Too many recipients. Reduce the number of recipients to $max.';

@ -360,5 +360,7 @@ $labels['replylist'] = 'Odpowiedz na listę';
$labels['editidents'] = 'Edytuj tożsamości';
$labels['addmailreplyto'] = 'Dodaj Mail-Reply-To';
$labels['addmailfollowupto'] = 'Dodaj Mail-Followup-To';
$labels['dsn'] = 'Status dostarczenia (DSN)';
$labels['reqdsn'] = 'Zawsze żądaj statusu dostarczenia (DSN)';
?>

@ -114,6 +114,7 @@ $messages['smtpautherror'] = 'Błąd SMTP ($code): Uwierzytelnianie nie powiodł
$messages['smtpfromerror'] = 'Błąd SMTP ($code): Nie można ustawić nadawcy "$from" ($msg)';
$messages['smtptoerror'] = 'Błąd SMTP ($code): Nie można dodać odbiorcy "$to" ($msg)';
$messages['smtprecipientserror'] = 'Błąd SMTP: Parsowanie listy odbiorców nie powiodło się';
$messages['smtpdsnerror'] = 'Błąd SMTP: Statusy dostarczenia (DSN) nie są obsługiwane przez serwer';
$messages['smtperror'] = 'Błąd SMTP: $msg';
$messages['emailformaterror'] = 'Błędny adres e-mail: $email';
$messages['toomanyrecipients'] = 'Zbyt wielu odbiorców. Zmniejsz ich liczbę do $max.';

@ -1174,6 +1174,28 @@ function rcmail_receipt_checkbox($attrib)
}
function rcmail_dsn_checkbox($attrib)
{
global $RCMAIL;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (!isset($attrib['id']))
$attrib['id'] = 'dsn';
$attrib['name'] = '_dsn';
$attrib['value'] = '1';
$checkbox = new html_checkbox($attrib);
$out = $form_start ? "$form_start\n" : '';
$out .= $checkbox->show($RCMAIL->config->get('dsn_default'));
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_editor_selector($attrib)
{
global $CONFIG, $MESSAGE, $compose_mode;
@ -1251,6 +1273,7 @@ $OUTPUT->add_handlers(array(
'priorityselector' => 'rcmail_priority_selector',
'editorselector' => 'rcmail_editor_selector',
'receiptcheckbox' => 'rcmail_receipt_checkbox',
'dsncheckbox' => 'rcmail_dsn_checkbox',
'storetarget' => 'rcmail_store_target_selection',
));

@ -1478,10 +1478,11 @@ function rcmail_compose_cleanup()
* @param array $mailto Array of recipient address strings
* @param array $smtp_error SMTP error array (reference)
* @param string $body_file Location of file with saved message body (reference)
* @param array $smtp_opts SMTP options (e.g. DSN request)
*
* @return boolean Send status.
*/
function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file)
function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file, $smtp_opts=null)
{
global $CONFIG, $RCMAIL;
@ -1525,7 +1526,7 @@ function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_
if (!is_object($RCMAIL->smtp))
$RCMAIL->smtp_init(true);
$sent = $RCMAIL->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body);
$sent = $RCMAIL->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body, $smtp_opts);
$smtp_response = $RCMAIL->smtp->get_response();
$smtp_error = $RCMAIL->smtp->get_error();

@ -546,7 +546,13 @@ if (!$savedraft)
$OUTPUT->send('iframe');
}
$sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto, $smtp_error, $mailbody_file);
// Handle Delivery Status Notification request
if (!empty($_POST['_dsn'])) {
$smtp_opts['dsn'] = true;
}
$sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto,
$smtp_error, $mailbody_file, $smtp_opts);
// return to compose page if sending failed
if (!$sent)

@ -524,6 +524,16 @@ function rcmail_user_prefs($current=null)
);
}
if (!isset($no_override['dsn_default'])) {
$field_id = 'rcmfd_dsn_default';
$input_dsn = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['dsn_default'] = array(
'title' => html::label($field_id, Q(rcube_label('reqdsn'))),
'content' => $input_dsn->show($config['dsn_default']?1:0),
);
}
if (!isset($no_override['top_posting'])) {
$field_id = 'rcmfd_top_posting';
$select_replymode = new html_select(array('name' => '_top_posting', 'id' => $field_id, 'onchange' => "\$('#rcmfd_sig_above').attr('disabled',this.selectedIndex==0)"));

@ -66,6 +66,7 @@ switch ($CURR_SECTION)
'mime_param_folding' => isset($_POST['_mime_param_folding']) ? intval($_POST['_mime_param_folding']) : 0,
'force_7bit' => isset($_POST['_force_7bit']) ? TRUE : FALSE,
'mdn_default' => isset($_POST['_mdn_default']) ? TRUE : FALSE,
'dsn_default' => isset($_POST['_dsn_default']) ? TRUE : FALSE,
'show_sig' => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 1,
'top_posting' => !empty($_POST['_top_posting']),
'strip_existing_sig' => isset($_POST['_strip_existing_sig']),

@ -136,6 +136,9 @@
<tr>
<td><label for="rcmcomposereceipt"><roundcube:label name="returnreceipt" />:</label></td>
<td><roundcube:object name="receiptCheckBox" form="form" id="rcmcomposereceipt" /></td>
</tr><tr>
<td><label for="rcmcomposedsn"><roundcube:label name="dsn" />:</label></td>
<td><roundcube:object name="dsnCheckBox" form="form" id="rcmcomposedsn" /></td>
</tr><tr>
<td><label for="rcmcomposepriority"><roundcube:label name="priority" />:</label></td>
<td><roundcube:object name="prioritySelector" form="form" id="rcmcomposepriority" /></td>

Loading…
Cancel
Save