1<?php
2
3/**
4 +-----------------------------------------------------------------------+
5 | This file is part of the Roundcube Webmail client                     |
6 |                                                                       |
7 | Copyright (C) The Roundcube Dev Team                                  |
8 |                                                                       |
9 | Licensed under the GNU General Public License version 3 or            |
10 | any later version with exceptions for skins & plugins.                |
11 | See the README file for a full license statement.                     |
12 |                                                                       |
13 | PURPOSE:                                                              |
14 |   Send a message disposition notification for a specific mail         |
15 +-----------------------------------------------------------------------+
16 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
17 +-----------------------------------------------------------------------+
18*/
19
20class rcmail_action_mail_sendmdn extends rcmail_action
21{
22    protected static $mode = self::MODE_AJAX;
23
24    /**
25     * Request handler.
26     *
27     * @param array $args Arguments from the previous step(s)
28     */
29    public function run($args = [])
30    {
31        $rcmail = rcmail::get_instance();
32
33        if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST)) {
34            $sent = self::send_mdn($uid, $smtp_error);
35        }
36
37        // show either confirm or error message
38        if (!empty($sent)) {
39            $rcmail->output->set_env('mdn_request', false);
40            $rcmail->output->show_message('receiptsent', 'confirmation');
41        }
42        else if (!empty($smtp_error) && is_string($smtp_error)) {
43            $rcmail->output->show_message($smtp_error, 'error');
44        }
45        else if (!empty($smtp_error) && !empty($smtp_error['label'])) {
46            $rcmail->output->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
47        }
48        else {
49            $rcmail->output->show_message('errorsendingreceipt', 'error');
50        }
51
52        // Redirect to 'addcontact' action to save the sender address
53        if (!empty($_POST['_save'])) {
54            if ($_POST['_save'] == 5) {
55                $_POST['_source'] = rcube_addressbook::TYPE_TRUSTED_SENDER;
56            }
57
58            $rcmail->action = 'addcontact';
59            return;
60        }
61
62        $rcmail->output->send();
63    }
64
65    /**
66     * Send the MDN response
67     *
68     * @param mixed        $message    Original message object (rcube_message) or UID
69     * @param array|string $smtp_error SMTP error array or (deprecated) string
70     *
71     * @return boolean Send status
72     */
73    public static function send_mdn($message, &$smtp_error)
74    {
75        $rcmail = rcmail::get_instance();
76
77        if (!is_object($message) || !is_a($message, 'rcube_message')) {
78            $message = new rcube_message($message);
79        }
80
81        if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) &&
82            ($rcmail->storage->check_permflag('MDNSENT') || $rcmail->storage->check_permflag('*'))
83        ) {
84            $charset   = $message->headers->charset;
85            $identity  = rcmail_sendmail::identity_select($message);
86            $sender    = format_email_recipient($identity['email'], $identity['name']);
87            $recipient = array_first(rcube_mime::decode_address_list($message->headers->mdn_to, 1, true, $charset));
88            $mailto    = $recipient['mailto'];
89
90            $compose = new Mail_mime("\r\n");
91
92            $compose->setParam('text_encoding', 'quoted-printable');
93            $compose->setParam('html_encoding', 'quoted-printable');
94            $compose->setParam('head_encoding', 'quoted-printable');
95            $compose->setParam('head_charset', RCUBE_CHARSET);
96            $compose->setParam('html_charset', RCUBE_CHARSET);
97            $compose->setParam('text_charset', RCUBE_CHARSET);
98
99            // compose headers array
100            $headers = [
101                'Date'       => $rcmail->user_date(),
102                'From'       => $sender,
103                'To'         => $message->headers->mdn_to,
104                'Subject'    => $rcmail->gettext('receiptread') . ': ' . $message->subject,
105                'Message-ID' => $rcmail->gen_message_id($identity['email']),
106                'X-Sender'   => $identity['email'],
107                'References' => trim($message->headers->references . ' ' . $message->headers->messageID),
108                'In-Reply-To' => $message->headers->messageID,
109            ];
110
111            $report = "Final-Recipient: rfc822; {$identity['email']}\r\n"
112                . "Original-Message-ID: {$message->headers->messageID}\r\n"
113                . "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
114
115            if ($message->headers->to) {
116                $report .= "Original-Recipient: {$message->headers->to}\r\n";
117            }
118
119            if ($agent = $rcmail->config->get('useragent')) {
120                $headers['User-Agent'] = $agent;
121                $report .= "Reporting-UA: $agent\r\n";
122            }
123
124            $to   = rcube_mime::decode_mime_string($message->headers->to, $charset);
125            $date = $rcmail->format_date($message->headers->date, $rcmail->config->get('date_long'));
126            $body = $rcmail->gettext("yourmessage") . "\r\n\r\n" .
127                "\t" . $rcmail->gettext("to") . ": {$to}\r\n" .
128                "\t" . $rcmail->gettext("subject") . ": {$message->subject}\r\n" .
129                "\t" . $rcmail->gettext("date") . ": {$date}\r\n" .
130                "\r\n" . $rcmail->gettext("receiptnote");
131
132            $compose->headers(array_filter($headers));
133            $compose->setContentType('multipart/report', ['report-type'=> 'disposition-notification']);
134            $compose->setTXTBody(rcube_mime::wordwrap($body, 75, "\r\n"));
135            $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
136
137            // SMTP options
138            $options = ['mdn_use_from' => (bool) $rcmail->config->get('mdn_use_from')];
139
140            $sent = $rcmail->deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options, true);
141
142            if ($sent) {
143                $rcmail->storage->set_flag($message->uid, 'MDNSENT');
144                return true;
145            }
146        }
147
148        return false;
149    }
150}
151