00001 <?php
00002 define('MAIL_LF', "\n");
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 class MailMessage {
00013
00014 const MIME_TEXT_PLAIN = 'text/plain; charset="%charset"';
00015
00016 const MIME_HTML = 'text/html; charset="%charset"';
00017
00018
00019
00020
00021
00022
00023 private $to = '';
00024
00025
00026
00027
00028
00029
00030 private $from = '';
00031
00032
00033
00034
00035
00036
00037 private $subject = '';
00038
00039
00040
00041
00042 private $message = '';
00043
00044
00045
00046
00047
00048 private $message_alt = '';
00049
00050
00051
00052
00053
00054
00055 private $cc = '';
00056
00057 private $content_type = '';
00058
00059
00060
00061
00062 private $files_to_attach = array();
00063
00064
00065
00066
00067 public function __construct($subject, $message, $to, $from = '', $content_type = '') {
00068 $this->subject = trim(Config::get_value(Config::MAIL_SUBJECT) . ' ' . $subject);
00069 $this->message = $message;
00070 $this->to = $to;
00071 $this->from = $from;
00072 if (empty($content_type)) {
00073 $this->content_type = self::MIME_TEXT_PLAIN;
00074 }
00075 else {
00076 $this->content_type = $content_type;
00077 }
00078 }
00079
00080
00081
00082
00083
00084
00085 public function send() {
00086
00087 $ret = $this->safety_validate_header();
00088 if ($ret->is_error()) {
00089 return $ret;
00090 }
00091
00092 $headers = array(
00093 'From' => empty($this->from) ? Config::get_value(Config::MAIL_SENDER, true) : $this->from,
00094 );
00095 if ($this->cc != '') {
00096 $headers['Bcc'] = $this->cc;
00097 }
00098
00099 $builder = $this->create_builder();
00100 $headers['Content-Type'] = $builder->get_mail_mime();
00101 $headers = array_merge($headers, $builder->get_additional_headers());
00102 $body = $builder->get_body();
00103
00104 $headers = $this->encode_headers($headers);
00105 $subject = ConverterFactory::encode($this->subject, ConverterFactory::MIMEHEADER);
00106 if (!mail($this->to, $subject, $body, Arr::implode("\n", $headers, ': '))) {
00107 $ret->append(tr('Could not send mail', 'core'));
00108 }
00109
00110 return $ret;
00111 }
00112
00113 protected function encode_headers($headers) {
00114 $ret = array();
00115 foreach($headers as $name => $value) {
00116 $ret[$name] = ConverterFactory::encode($value, ConverterFactory::MIMEHEADER);
00117 }
00118 return $ret;
00119 }
00120
00121
00122
00123
00124
00125
00126 protected function create_builder() {
00127 $ret = false;
00128 Load::directories('lib/components/mailmessagebuilder');
00129 $msg_builder = ($this->message_alt)
00130 ? new AlternativeMessageBuilder($this->message, $this->content_type, $this->message_alt)
00131 : new SingleMessageBuilder($this->message, $this->content_type);
00132 if (count($this->files_to_attach)) {
00133 $ret = new AttachmentsBuilder($msg_builder, $this->files_to_attach);
00134 }
00135 else {
00136 $ret = $msg_builder;
00137 }
00138 return $ret;
00139 }
00140
00141
00142
00143
00144 public function add_attachment($file_name, $name = '') {
00145 if ($name == '') {
00146 $name = $file_name;
00147 }
00148 $this->files_to_attach[$name] = $file_name;
00149 }
00150
00151
00152
00153
00154
00155 public function preprocess_header() {
00156 $this->to = $this->safety_preprocess_header_field($this->to);
00157 $this->from = $this->safety_preprocess_header_field($this->from);
00158 $this->subject = $this->safety_preprocess_header_field($this->subject);
00159 $this->cc = $this->safety_preprocess_header_field($this->cc);
00160 }
00161
00162
00163
00164
00165 public function set_alt_message($msg) {
00166 $this->message_alt = $msg;
00167 }
00168
00169
00170
00171
00172
00173 private function safety_preprocess_header_field($value) {
00174 $ret = str_replace("\r", '', $value);
00175 $ret = str_replace("\n", '', $ret);
00176
00177
00178
00179 $find = array("/bcc\:/i", "/Content\-Type\:/i", "/Mime\-Type\:/i", "/cc\:/i", "/to\:/i");
00180 $ret = preg_replace($find, '**bogus header removed**', $ret);
00181
00182 return $ret;
00183 }
00184
00185
00186
00187
00188 private function safety_validate_header() {
00189 $ret = new Status();
00190 $ret->merge($this->safety_check_header_field($this->to, 'Empfänger'));
00191 $ret->merge($this->safety_check_header_field($this->from, 'Absender'));
00192 $ret->merge($this->safety_check_header_field($this->subject, 'Betreff'));
00193 $ret->merge($this->safety_check_header_field($this->cc, 'CC'));
00194 $ret->merge($this->safety_check_header_field($this->content_type, 'Content-Tye'));
00195 $ret->merge($this->safety_check_exploit_strings($this->message, 'Nachricht', true));
00196 return $ret;
00197 }
00198
00199 private function safety_check_header_field(&$value, $type) {
00200 if (strpos($value, "\r") !== false || strpos($value, "\n") !== false) {
00201 return new Status($type. ': Zeilenumbrüche sind nicht erlaubt.');
00202 }
00203
00204 return $this->safety_check_exploit_strings($value, $type, false);
00205 }
00206
00207 private function safety_check_exploit_strings(&$value, $type, $beginLineOnly = false) {
00208 $err = new Status();
00209 $find = array($this->safety_prepare_exploit_string("bcc" , $beginLineOnly),
00210 $this->safety_prepare_exploit_string("Content\-Type" , $beginLineOnly),
00211 $this->safety_prepare_exploit_string("Mime\-Type" , $beginLineOnly),
00212 $this->safety_prepare_exploit_string('cc' , $beginLineOnly),
00213 $this->safety_prepare_exploit_string('to' , $beginLineOnly));
00214 $temp = preg_replace($find, '**!HEADERINJECTION!**', $value);
00215 if (strpos($temp, '**!HEADERINJECTION!**') !== false) {
00216 $err->append($type . ': "To:", "Bcc:", "Subject:" und weitere reservierte Wörter eines E-Mail-Headers sind nicht erlaubt.');
00217 }
00218
00219 return $err;
00220 }
00221
00222 private function safety_prepare_exploit_string($val, $multiline) {
00223 if ($multiline)
00224 return "/^" . $val . "\:/im";
00225 else
00226 return "/" . $val . "\:/i";
00227 }
00228 }