4 protected $header = array();
5 protected $env_from = false;
6 protected $attachments = array();
7 protected $CRLF = "\r\n";
9 public function set($name, $value)
11 $this->header[$name][] = $value;
14 public function env_from($value)
16 $this->env_from = $value;
19 protected function contentType($path)
21 if (($fh = popen('/usr/bin/file -i -b ' . escapeshellarg(realpath($path)), 'r')) !== false) {
22 $type = fread($fh, 1024);
24 $parts = explode(';', $type);
25 return trim($parts[0]);
27 return mime_content_type($file);
30 public function attach($content, $type=false, $first=false)
32 $part = new stdClass();
34 if ($type === false) {
35 if (file_exists($content)) {
36 $part->content = chunk_split(base64_encode(file_get_contents($content)));
37 $part->header = 'Content-Type: ' . $this->contentType($content) . '; name="'.basename($content).'"'. $this->CRLF .
38 'Content-Transfer-Encoding: base64' . $this->CRLF .
39 'Content-Disposition: attachment';
41 } elseif (substr($type, 0, 10) == 'text/plain' ||
42 substr($type, 0, 9) == 'text/html') {
43 if (strpos($type, 'charset=') === false)
44 $type .= '; charset="UTF-8"';
45 $part->content = $content;
46 $part->header = 'Content-Type: ' . $type . $this->CRLF .
47 'Content-Transfer-Encoding: 8bit';
49 $part->content = chunk_split(base64_encode($content));
50 $part->header = 'Content-Type: ' . $type . $this->CRLF .
51 'Content-Transfer-Encoding: base64' . $this->CRLF .
52 'Content-Disposition: attachment';
55 if (!empty($part->content)) {
57 array_unshift($this->attachments, $part);
59 $this->attachments[] = $part;
63 public function send($body=false)
65 if (!array_key_exists('From', $this->header))
66 throw new Exception('No sender given.');
67 if (!array_key_exists('To', $this->header))
68 throw new Exception('No recipient given.');
69 if (!array_key_exists('Subject', $this->header))
70 throw new Exception('No subject given.');
71 if (!count($this->attachments) && empty($body))
72 throw new Exception('Mail body empty and no attachments.');
74 if (count($this->attachments)) {
75 $boundary = md5(uniqid(time()));
76 $this->header['MIME-Version'] = array('1.0');
77 $this->header['Content-Type'] = array('multipart/mixed; boundary="'.$boundary.'"');
79 $this->attach($body, substr($body,0,1) == '<' ? 'text/html' : 'text/plain', true);
81 if (!array_key_exists('Content-Type', $this->header)) {
82 if ($body && substr($body,0,1) == '<')
83 $this->set('Content-Type', 'text/html; charset=UTF-8');
85 $this->set('Content-Type', 'text/plain; charset=UTF-8');
87 if (!array_key_exists('Content-Disposition', $this->header))
88 $this->set('Content-Disposition', 'inline');
89 if (!array_key_exists('Content-Transfer-Encoding', $this->header))
90 $this->set('Content-Transfer-Encoding', '8bit');
94 $to = implode(', ', $this->header['To']);
95 if (defined('MAIL_DISABLED') && MAIL_DISABLED !== false) {
96 $header .= 'Orig-To: ' . $to . $this->CRLF;
99 if (array_key_exists('Cc', $this->header)) {
100 $this->header['Orig-Cc'] = $this->header['Cc'];
101 unset($this->header['Cc']);
103 if (array_key_exists('Bcc', $this->header)) {
104 $this->header['Orig-Bcc'] = $this->header['Bcc'];
105 unset($this->header['Bcc']);
108 foreach ($this->header as $name => $values) {
109 if ($name == 'To' || $name == 'Subject')
112 $header .= $name . ': ' . implode(', ', $values) . $this->CRLF;
116 $opts .= strlen($this->env_from) ? ' -f '.$this->env_from : '';
118 $header = substr($header,0,-strlen($this->CRLF));
119 if (count($this->attachments)) {
120 $header .= $this->CRLF . "This is a MIME encoded message." . $this->CRLF;
122 foreach ($this->attachments as $part) {
123 $header .= "--$boundary" . $this->CRLF;
124 $header .= $part->header . $this->CRLF;
125 $header .= $this->CRLF . $part->content . $this->CRLF;
127 $header .= "--$boundary--";
129 $result = mail($to, $this->header['Subject'][0], '', $header, $opts);
131 $result = mail($to, $this->header['Subject'][0], $body, $header, $opts);
134 Application::debug(sprintf('Send Mail "%s" to %s', $this->header['Subject'][0], $this->header['To'][0]));