Passed
Push — master ( ab8fe6...63c0b4 )
by Andreas
27:23
created

org_openpsa_mail_message::get_headers()   A

Complexity

Conditions 5
Paths 10

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 10
nop 0
dl 0
loc 17
ccs 10
cts 10
cp 1
crap 5
rs 9.6111
c 0
b 0
f 0
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, string $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(string $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 (in_array(strtolower($header), ['from', 'reply-to', 'to'])) {
104 4
                $this->_headers[$header] = $this->_encode_address_field($value);
105
            }
106
        }
107
108 4
        return $this->_headers;
109
    }
110
111 4
    public function get_body()
112
    {
113 4
        return $this->_body;
114
    }
115
116 3
    public function set_body($body)
117
    {
118 3
        $this->_body = $body;
119 3
        $this->_html_body = null;
120 3
    }
121
122 1
    public function set_html_body(string $body, string $altBody, array $attachments, bool $do_image_embedding)
123
    {
124 1
        $this->_body = $altBody;
125 1
        $this->_html_body = $body;
126
127
        // adjust html body
128 1
        if ($do_image_embedding) {
129
            $this->_embed_images();
130
        }
131
132
        // process attachments
133 1
        $this->_process_attachments($attachments);
134 1
    }
135
136
    private function _embed_images()
137
    {
138
        // anything with SRC = "" something in it (images etc)
139
        $regExp_src = "/(src|background)=([\"'�])(((https?|ftp):\/\/)?(.*?))\\2/i";
140
        preg_match_all($regExp_src, $this->_html_body, $matches_src);
141
        debug_print_r("matches_src:", $matches_src);
142
143
        $matches = [
144
            "whole" => $matches_src[0],
145
            "uri" => $matches_src[3],
146
            "proto" => $matches_src[4],
147
            "location" => $matches_src[6]
148
        ];
149
150
        foreach ($matches["whole"] as $key => $match) {
151
            $location = $matches["location"][$key];
152
            // uri is fully qualified
153
            if ($matches['proto'][$key]) {
154
                $uri = $matches["uri"][$key];
155
            }
156
            // uri is relative
157
            elseif (preg_match('/^\//', $location)) {
158
                $uri = midcom::get()->get_host_name() . $location;
159
            } else {
160
                debug_add('No usable uri found, skipping embed', MIDCOM_LOG_WARN);
161
                continue;
162
            }
163
164
            // replace src by swiftmailer embedded image
165
            $repl = $this->_message->embed(Swift_Image::fromPath($uri));
166
            $new_html = str_replace($location, $repl, $match);
167
            $this->_html_body = str_replace($match, $new_html, $this->_html_body);
168
        }
169
    }
170
171 1
    private function _process_attachments(array $attachments)
172
    {
173 1
        foreach ($attachments as $att) {
174
            if (empty($att['mimetype'])) {
175
                $att['mimetype'] = "application/octet-stream";
176
            }
177
178
            $swift_att = false;
179
            // we got a file path
180
            if (!empty($att['file'])) {
181
                $swift_att = Swift_Attachment::fromPath($att['file'], $att['mimetype']);
182
            }
183
            // we got the contents (bytes)
184
            elseif (!empty($att['content'])) {
185
                $swift_att = new Swift_Attachment($att['content'], $att['name'], $att['mimetype']);
186
            }
187
188
            if ($swift_att) {
189
                $this->_message->attach($swift_att);
190
            }
191
        }
192 1
    }
193
194
    /**
195
     * Helper function that provides backwards compatibility
196
     * to addresses specified in a "Name <[email protected]>" format
197
     *
198
     * @param string $value The value to encode
199
     * @return mixed the encoded value
200
     */
201 4
    private function _encode_address_field($value)
202
    {
203 4
        if (is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
204
            array_walk($value, [$this, '_encode_address_field']);
205
            return $value;
206
        }
207 4
        if ($pos = strpos($value, '<')) {
208 1
            $name = substr($value, 0, $pos);
209 1
            $name = preg_replace('/^\s*"/', '', $name);
210 1
            $name = preg_replace('/"\s*$/', '', $name);
211 1
            $address = substr($value, $pos + 1);
212 1
            $address = substr($address, 0, strlen($address) - 1);
213 1
            $value = [$address => $name];
214
        }
215 4
        return $value;
216
    }
217
}
218