source: subversion/trunk/roundcubemail/program/steps/mail/sendmail.inc @ 73

Last change on this file since 73 was 73, checked in by roundcube, 8 years ago

Added more XSS protection (Bug #1308236) and some visual enhancements

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1<?php
2
3/*
4 +-----------------------------------------------------------------------+
5 | program/steps/mail/sendmail.inc                                       |
6 |                                                                       |
7 | This file is part of the RoundCube Webmail client                     |
8 | Copyright (C) 2005, RoundCube Dev. - Switzerland                      |
9 | Licensed under the GNU GPL                                            |
10 |                                                                       |
11 | PURPOSE:                                                              |
12 |   Compose a new mail message with all headers and attachments         |
13 |   and send it using IlohaMail's SMTP methods or with PHP mail()       |
14 |                                                                       |
15 +-----------------------------------------------------------------------+
16 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
17 +-----------------------------------------------------------------------+
18
19 $Id$
20
21*/
22
23
24//require_once('lib/smtp.inc');
25require_once('include/rcube_smtp.inc');
26require_once('Mail/mime.php');
27
28
29if (!isset($_SESSION['compose']['id']))
30  {
31  $_action = 'list';
32  return;
33  }
34
35
36/****** message sending functions ********/
37
38
39
40function rcmail_get_identity($id)
41  {
42  global $DB;
43 
44  // get identity record
45  $sql_result = $DB->query("SELECT *, email AS mailto
46                            FROM ".get_table_name('identities')."
47                            WHERE  identity_id=?
48                            AND    user_id=?
49                            AND    del<>'1'",
50                            $id,$_SESSION['user_id']);
51                                   
52  if ($DB->num_rows($sql_result))
53    {
54    $sql_arr = $DB->fetch_assoc($sql_result);
55    $out = $sql_arr;
56    $out['string'] = sprintf('%s <%s>', $sql_arr['name'], $sql_arr['mailto']);
57    return $out;
58    }
59
60  return FALSE; 
61  }
62
63
64
65/****** check submission and compose message ********/
66
67
68$mailto_regexp = array('/,\s*[\r\n]+/', '/[\r\n]+/', '/,\s*$/m');
69$mailto_replace = array(' ', ', ', '');
70
71// repalce new lines and strip ending ', '
72$mailto = preg_replace($mailto_regexp, $mailto_replace, stripslashes($_POST['_to']));
73
74// decode address strings
75$to_address_arr = $IMAP->decode_address_list($mailto);
76$identity_arr = rcmail_get_identity($_POST['_from']);
77
78
79$from = $identity_arr['mailto'];
80$first_to = is_array($to_address_arr[0]) ? $to_address_arr[0]['mailto'] : $mailto;
81
82
83// create unique message-id
84$message_id = sprintf('<%s@%s>', md5(uniqid('rcmail')), $_SESSION['imap_host']);
85
86
87// compose headers array
88$headers = array('Date' => date('D, j M Y G:i:s O'),
89                 'From' => $identity_arr['string'],
90                 'To'   => $mailto);
91
92// additional recipients
93if ($_POST['_cc'])
94  $headers['Cc'] = preg_replace($mailto_regexp, $mailto_replace, stripslashes($_POST['_cc']));
95
96if ($_POST['_bcc'])
97  $headers['Bcc'] = preg_replace($mailto_regexp, $mailto_replace, stripslashes($_POST['_bcc']));
98 
99if (strlen($identity_arr['bcc']))
100  $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc'];
101
102// add subject
103$headers['Subject'] = trim(stripslashes($_POST['_subject']));
104
105if (strlen($identity_arr['organization']))
106  $headers['Organization'] = $identity_arr['organization'];
107
108if (strlen($identity_arr['reply-to']))
109  $headers['Reply-To'] = $identity_arr['reply-to'];
110
111if ($_SESSION['compose']['reply_msgid'])
112  $headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid'];
113
114
115if ($_POST['_priority'])
116  {
117  $priority = (int)$_POST['_priority'];
118  $a_priorities = array(1=>'lowest', 2=>'low', 4=>'high', 5=>'highest');
119  if ($str_priority = $a_priorities[$priority])
120    $headers['X-Priority'] = sprintf("%d (%s)", $priority, ucfirst($str_priority));
121  }
122
123
124// additional headers
125$headers['Message-ID'] = $message_id;
126$headers['X-Sender'] = $from;
127
128if ($CONFIG['useragent'])
129  $headers['User-Agent'] = $CONFIG['useragent'];
130
131
132// create PEAR::Mail_mime instance
133$MAIL_MIME = new Mail_mime();
134$MAIL_MIME->setTXTBody(stripslashes($_POST['_message']), FALSE, TRUE);
135//$MAIL_MIME->setTXTBody(wordwrap(stripslashes($_POST['_message'])), FALSE, TRUE);
136
137
138// add stored attachments, if any
139if (is_array($_SESSION['compose']['attachments']))
140  foreach ($_SESSION['compose']['attachments'] as $attachment)
141    $MAIL_MIME->addAttachment($attachment['path'], $attachment['mimetype'], $attachment['name'], TRUE);
142
143 
144// add submitted attachments
145if (is_array($_FILES['_attachments']['tmp_name']))
146  foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath)
147    $MAIL_MIME->addAttachment($filepath, $files['type'][$i], $files['name'][$i], TRUE);
148
149// encoding settings for mail composing
150$message_param = array('text_encoding' => '7bit',
151                       'html_encoding' => 'quoted-printable',
152                       'head_encoding' => 'quoted-printable',
153                       'head_charset'  => 'ISO-8859-1',
154                       'html_charset'  => 'ISO-8859-1',
155                       'text_charset'  => 'ISO-8859-1');
156
157// compose message body and get headers
158$msg_body = $MAIL_MIME->get($message_param);
159$msg_subject = $headers['Subject'];
160
161
162// send thru SMTP server using cusotm SMTP library
163if ($CONFIG['smtp_server'])
164  {
165  // generate list of recipients
166  $a_recipients = array($mailto);
167
168  if (strlen($headers['Cc']))
169    $a_recipients[] = $headers['Cc'];
170  if (strlen($headers['Bcc']))
171    $a_recipients[] = $headers['Bcc'];
172
173  // generate message headers
174  $header_str = $MAIL_MIME->txtHeaders($headers);
175
176  // send message
177  $sent = smtp_mail($from, $a_recipients, $header_str, $msg_body);
178
179  // log error
180  if (!$sent)
181    {
182    raise_error(array('code' => 800,
183                      'type' => 'smtp',
184                      'line' => __LINE__,
185                      'file' => __FILE__,
186                      'message' => "SMTP error: $SMTP_ERROR"), TRUE, FALSE);
187    }
188  }
189
190// send mail using PHP's mail() function
191else
192  {
193  // unset some headers because they will be added by the mail() function
194  $headers_php = $headers;
195  unset($headers_php['To'], $headers_php['Subject']);
196
197  $header_str = $MAIL_MIME->txtHeaders($headers_php);
198 
199  if(ini_get('safe_mode'))
200    $sent = mail($mailto, $msg_subject, $msg_body, $header_str);
201  else 
202    $sent = mail($mailto, $msg_subject, $msg_body, $header_str, "-f$from");
203  }
204
205
206// return to compose page if sending failed
207if (!$sent)
208  {
209  $_action = 'compose';
210  $OUTPUT->add_script(sprintf("\n%s.set_env('action', '%s');", $JS_OBJECT_NAME, $_action));
211  show_message("sendingfailed", 'error');
212  return;
213  }
214
215
216// set repliead flag
217if ($_SESSION['compose']['reply_uid'])
218  $IMAP->set_flag($_SESSION['compose']['reply_uid'], 'ANSWERED');
219
220
221// copy message to sent folder
222if ($CONFIG['sent_mbox'])
223  {
224  // create string of complete message headers
225  $header_str = $MAIL_MIME->txtHeaders($headers);
226
227  // check if mailbox exists
228  if (!in_array_nocase($CONFIG['sent_mbox'], $IMAP->list_mailboxes()))
229    $mbox = $IMAP->create_mailbox($CONFIG['sent_mbox'], TRUE);
230  else
231    $mbox = TRUE;
232
233  // append message to sent box
234  if ($mbox)
235    $saved = $IMAP->save_message($CONFIG['sent_mbox'], $header_str."\r\n".$msg_body);
236
237  // raise error if saving failed
238  if (!$saved)
239    raise_error(array('code' => 800,
240                      'type' => 'imap',
241                      'file' => __FILE__,
242                      'message' => "Could not save message in $CONFIG[sent_mbox]"), TRUE, FALSE);
243  }
244
245
246// log mail sending
247if ($CONFIG['smtp_log'])
248  {
249  $log_entry = sprintf("[%s] User: %d; Message for %s; Subject: %s\n",
250               date("d-M-Y H:i:s O", mktime()),
251               $_SESSION['user_id'],
252               $mailto,
253               $msg_subject);
254
255  if ($fp = fopen($INSTALL_PATH.'logs/sendmail', 'a'))
256    {
257    fwrite($fp, $log_entry);
258    fclose($fp);
259    }
260  }
261
262
263// show confirmation
264show_message('messagesent', 'confirmation');
265
266
267// kill compose entry from session
268rcmail_compose_cleanup();
269
270?>
Note: See TracBrowser for help on using the repository browser.