Passed
Push — master ( 3a5439...237bdc )
by Andreas
19:53
created

org_openpsa_mail_message::_embed_images()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 20
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 32
ccs 0
cts 19
cp 0
crap 20
rs 9.6
1
<?php
2
/**
3
 * @package org.openpsa.mail
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
/**
10
 * Wrapper class for emails
11
 *
12
 * @package org.openpsa.mail
13
 */
14
class org_openpsa_mail_message
15
{
16
    private $_to;
17
18
    private $_encoding;
19
20
    private $_headers;
21
22
    private $_body;
23
    private $_html_body;
24
25
    /**
26
     *
27
     * @var Swift_Message
28
     */
29
    private $_message;
30
31 4
    public function __construct($to, array $headers, $encoding)
32
    {
33 4
        $this->_to = $this->_encode_address_field($to);
34 4
        $this->_headers = $headers;
35 4
        $this->_encoding = $encoding;
36
37 4
        $this->_message = new Swift_Message('');
38 4
    }
39
40 4
    public function get_recipients()
41
    {
42 4
        return $this->_to;
43
    }
44
45
    public function get_message() : Swift_Message
46
    {
47
        // set headers
48
        $headers_setter_map = [
49
            "content-type" => "setContentType",
50
            "content-description" => "setDescription",
51
            "from" => "setFrom",
52
            "to" => "setTo",
53
            "cc" => "setCc",
54
            "bcc" => "setBcc",
55
            "reply-to" => "setReplyTo",
56
            "subject" => "setSubject",
57
            "date" => "setDate",
58
            "return-path" => "setReturnPath"
59
        ];
60
61
        // map headers we got to swift setter methods
62
        $msg_headers = $this->_message->getHeaders();
63
        $headers = $this->get_headers();
64
        foreach ($headers as $name => $value) {
65
            if (array_key_exists(strtolower($name), $headers_setter_map)) {
66
                $setter = $headers_setter_map[strtolower($name)];
67
                $this->_message->$setter($value);
68
            } elseif ($msg_headers->has($name)) {
69
                // header already exists => just set a new value
70
                $msg_headers->get($name)->setValue($value);
0 ignored issues
show
Bug introduced by
The method setValue() does not exist on Swift_Mime_Header. It seems like you code against a sub-type of Swift_Mime_Header such as Swift_Mime_Headers_OpenDKIMHeader or Swift_Mime_Headers_UnstructuredHeader. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
                $msg_headers->get($name)->/** @scrutinizer ignore-call */ setValue($value);
Loading history...
71
            } else {
72
                $msg_headers->addTextHeader($name, $value);
73
            }
74
        }
75
76
        // somehow we need to set the body after the headers...
77
        if (!empty($this->_html_body)) {
78
            $this->_message->setBody($this->_html_body, 'text/html');
79
            $this->_message->addPart($this->_body, 'text/plain');
80
        } else {
81
            $this->_message->setBody($this->_body, 'text/plain');
82
        }
83
84
        return $this->_message;
85
    }
86
87
    public function set_header_field($name, $value)
88
    {
89
        $this->_headers[$name] = $value;
90
    }
91
92 4
    public function get_headers() : array
93
    {
94 4
        if (empty($this->_headers['Content-Type'])) {
95 4
            $this->_headers['Content-Type'] = "text/plain; charset={$this->_encoding}";
96
        }
97
98 4
        reset($this->_headers);
99 4
        foreach ($this->_headers as $header => $value) {
100 4
            if (is_string($value)) {
101 4
                $this->_headers[$header] = trim($value);
102
            }
103 4
            if (   strtolower($header) == 'from'
104 4
                || strtolower($header) == 'reply-to'
105 4
                || strtolower($header) == 'to') {
106 4
                $this->_headers[$header] = $this->_encode_address_field($value);
107
            }
108
        }
109
110 4
        return $this->_headers;
111
    }
112
113 4
    public function get_body()
114
    {
115 4
        return $this->_body;
116
    }
117
118 3
    public function set_body($body)
119
    {
120 3
        $this->_body = $body;
121 3
        $this->_html_body = null;
122 3
    }
123
124
    /**
125
     *
126
     * @param string $body the html body
127
     * @param string $altBody the alternative (text) body
128
     * @param array $attachments
129
     * @param boolean $do_image_embedding
130
     */
131 1
    public function set_html_body($body, $altBody, $attachments, $do_image_embedding)
132
    {
133 1
        $this->_body = $altBody;
134 1
        $this->_html_body = $body;
135
136
        // adjust html body
137 1
        if ($do_image_embedding) {
138
            $this->_embed_images();
139
        }
140
141
        // process attachments
142 1
        $this->_process_attachments($attachments);
143 1
    }
144
145
    private function _embed_images()
146
    {
147
        // anything with SRC = "" something in it (images etc)
148
        $regExp_src = "/(src|background)=([\"'�])(((https?|ftp):\/\/)?(.*?))\\2/i";
149
        preg_match_all($regExp_src, $this->_html_body, $matches_src);
150
        debug_print_r("matches_src:", $matches_src);
151
152
        $matches = [
153
            "whole" => $matches_src[0],
154
            "uri" => $matches_src[3],
155
            "proto" => $matches_src[4],
156
            "location" => $matches_src[6]
157
        ];
158
159
        foreach ($matches["whole"] as $key => $match) {
160
            $location = $matches["location"][$key];
161
            // uri is fully qualified
162
            if ($matches['proto'][$key]) {
163
                $uri = $matches["uri"][$key];
164
            }
165
            // uri is relative
166
            elseif (preg_match('/^\//', $location)) {
167
                $uri = midcom::get()->get_host_name() . $location;
168
            } else {
169
                debug_add('No usable uri found, skipping embed', MIDCOM_LOG_WARN);
170
                continue;
171
            }
172
173
            // replace src by swiftmailer embedded image
174
            $repl = $this->_message->embed(Swift_Image::fromPath($uri));
175
            $new_html = str_replace($location, $repl, $match);
176
            $this->_html_body = str_replace($match, $new_html, $this->_html_body);
177
        }
178
    }
179
180 1
    private function _process_attachments($attachments)
181
    {
182 1
        foreach ($attachments as $att) {
183
            if (empty($att['mimetype'])) {
184
                $att['mimetype'] = "application/octet-stream";
185
            }
186
187
            $swift_att = false;
188
            // we got a file path
189
            if (!empty($att['file'])) {
190
                $swift_att = Swift_Attachment::fromPath($att['file'], $att['mimetype']);
191
            }
192
            // we got the contents (bytes)
193
            elseif (!empty($att['content'])) {
194
                $swift_att = new Swift_Attachment($att['content'], $att['name'], $att['mimetype']);
195
            }
196
197
            if ($swift_att) {
198
                $this->_message->attach($swift_att);
199
            }
200
        }
201 1
    }
202
203
    /**
204
     * Helper function that provides backwards compatibility
205
     * to addresses specified in a "Name <[email protected]>" format
206
     *
207
     * @param string $value The value to encode
208
     * @return mixed the encoded value
209
     */
210 4
    private function _encode_address_field($value)
211
    {
212 4
        if (is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
213
            array_walk($value, [$this, '_encode_address_field']);
214
            return $value;
215
        }
216 4
        if (strpos($value, '<')) {
217 1
            $name = substr($value, 0, strpos($value, '<'));
218 1
            $name = preg_replace('/^\s*"/', '', $name);
219 1
            $name = preg_replace('/"\s*$/', '', $name);
220 1
            $address = substr($value, strpos($value, '<') + 1);
221 1
            $address = substr($address, 0, strlen($address) - 1);
222 1
            $value = [$address => $name];
223
        }
224 4
        return $value;
225
    }
226
}
227