Passed
Push — master ( b3294c...789bfa )
by Andreas
11:15
created

org_openpsa_mail_message   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Test Coverage

Coverage 47.37%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 84
c 2
b 0
f 0
dl 0
loc 172
ccs 36
cts 76
cp 0.4737
rs 10
wmc 26

10 Methods

Rating   Name   Duplication   Size   Complexity  
A get_recipients() 0 3 1
A __construct() 0 7 1
A get_body() 0 3 1
B get_message() 0 40 6
A set_html_body() 0 12 2
A get_headers() 0 10 3
A set_header_field() 0 3 1
A set_body() 0 4 1
A _embed_images() 0 41 5
A _process_attachments() 0 14 5
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
use Symfony\Component\Mime\Email;
10
use Symfony\Component\Mime\Part\DataPart;
11
use Symfony\Component\Mime\MimeTypes;
12
13
/**
14
 * Wrapper class for emails
15
 *
16
 * @package org.openpsa.mail
17
 */
18
class org_openpsa_mail_message
19
{
20
    private $_to;
21
22
    private $_encoding;
23
24
    private $_headers;
25
26
    private $_body;
27
    private $_html_body;
28
29
    /**
30
     * @var Email
31
     */
32
    private $_message;
33
34 8
    public function __construct($to, array $headers, string $encoding)
35
    {
36 8
        $this->_to = $to;
37 8
        $this->_headers = $headers;
38 8
        $this->_encoding = $encoding;
39
40 8
        $this->_message = new Email;
41
    }
42
43 8
    public function get_recipients()
44
    {
45 8
        return $this->_to;
46
    }
47
48
    public function get_message() : Email
49
    {
50
        // set headers
51
        $headers_setter_map = [
52
            "from" => "from",
53
            "to" => "to",
54
            "cc" => "cc",
55
            "bcc" => "bcc",
56
            "reply-to" => "replyTo",
57
            "subject" => "subject",
58
            "date" => "date",
59
            "return-path" => "returnPath"
60
        ];
61
62
        // map headers we got to sf mailer setter methods
63
        $msg_headers = $this->_message->getHeaders();
64
65
        foreach ($this->get_headers() as $name => $value) {
66
            if (array_key_exists(strtolower($name), $headers_setter_map)) {
67
                $setter = $headers_setter_map[strtolower($name)];
68
                if (is_array($value)) {
69
                    $this->_message->$setter(...$value);
70
                } else {
71
                    $this->_message->$setter($value);
72
                }
73
            } elseif ($msg_headers->has($name)) {
74
                // header already exists => just set a new value
75
                $msg_headers->get($name)->setValue($value);
0 ignored issues
show
Bug introduced by
The method setValue() does not exist on Symfony\Component\Mime\Header\HeaderInterface. It seems like you code against a sub-type of Symfony\Component\Mime\Header\HeaderInterface such as Symfony\Component\Mime\Header\UnstructuredHeader. ( Ignorable by Annotation )

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

75
                $msg_headers->get($name)->/** @scrutinizer ignore-call */ setValue($value);
Loading history...
76
            } else {
77
                $msg_headers->addTextHeader($name, $value);
78
            }
79
        }
80
81
        // somehow we need to set the body after the headers...
82
        if (!empty($this->_html_body)) {
83
            $this->_message->html($this->_html_body);
84
        }
85
        $this->_message->text($this->_body);
86
87
        return $this->_message;
88
    }
89
90
    public function set_header_field(string $name, $value)
91
    {
92
        $this->_headers[$name] = $value;
93
    }
94
95 8
    public function get_headers() : array
96
    {
97 8
        reset($this->_headers);
98 8
        foreach ($this->_headers as $header => $value) {
99 8
            if (is_string($value)) {
100 8
                $this->_headers[$header] = trim($value);
101
            }
102
        }
103
104 8
        return $this->_headers;
105
    }
106
107 8
    public function get_body()
108
    {
109 8
        return $this->_body;
110
    }
111
112 6
    public function set_body($body)
113
    {
114 6
        $this->_body = $body;
115 6
        $this->_html_body = null;
116
    }
117
118 2
    public function set_html_body(string $body, string $altBody, array $attachments, bool $do_image_embedding)
119
    {
120 2
        $this->_body = $altBody;
121 2
        $this->_html_body = $body;
122
123
        // adjust html body
124 2
        if ($do_image_embedding) {
125 1
            $this->_embed_images();
126
        }
127
128
        // process attachments
129 2
        $this->_process_attachments($attachments);
130
    }
131
132 1
    private function _embed_images()
133
    {
134
        // anything with SRC = "" something in it (images etc)
135 1
        $regExp_src = "/(src|background)=([\"'�])(((https?|ftp):\/\/)?(.*?))\\2/i";
136 1
        preg_match_all($regExp_src, $this->_html_body, $matches_src);
137 1
        debug_print_r("matches_src:", $matches_src);
138
139 1
        $matches = [
140 1
            "whole" => $matches_src[0],
141 1
            "uri" => $matches_src[3],
142 1
            "proto" => $matches_src[4],
143 1
            "location" => $matches_src[6]
144
        ];
145
146 1
        foreach ($matches["whole"] as $key => $match) {
147
            $location = $matches["location"][$key];
148
            // uri is fully qualified
149
            if ($matches['proto'][$key]) {
150
                $uri = $matches["uri"][$key];
151
            }
152
            // uri is absolute
153
            elseif (str_starts_with($location, '/')) {
154
                $uri = midcom::get()->get_host_name() . $location;
155
            } else {
156
                debug_add('No usable uri found, skipping embed', MIDCOM_LOG_WARN);
157
                continue;
158
            }
159
160
            // replace src by embedded image
161
            $name = basename($uri);
162
            $mimetype = null;
163
            if ($ext = pathinfo($name, PATHINFO_EXTENSION)) {
164
                $mimetype = (new MimeTypes)->getMimeTypes($ext)[0] ?? null;
0 ignored issues
show
Bug introduced by
It seems like $ext can also be of type array; however, parameter $ext of Symfony\Component\Mime\MimeTypes::getMimeTypes() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

164
                $mimetype = (new MimeTypes)->getMimeTypes(/** @scrutinizer ignore-type */ $ext)[0] ?? null;
Loading history...
165
            }
166
167
            $part = (new DataPart(fopen($uri, 'r'), $name, $mimetype))
168
                ->asInline();
169
            $this->_message->attachPart($part);
170
171
            $new_html = str_replace($location, 'cid:' . $part->getContentId(), $match);
172
            $this->_html_body = str_replace($match, $new_html, $this->_html_body);
173
        }
174
    }
175
176 2
    private function _process_attachments(array $attachments)
177
    {
178 2
        foreach ($attachments as $att) {
179
            if (empty($att['mimetype'])) {
180
                $att['mimetype'] = "application/octet-stream";
181
            }
182
183
            // we got a file path
184
            if (!empty($att['file'])) {
185
                $this->_message->attachFromPath($att['file'], $att['name'], $att['mimetype']);
186
            }
187
            // we got the contents (bytes)
188
            elseif (!empty($att['content'])) {
189
                $this->_message->attach($att['content'], $att['name'], $att['mimetype']);
190
            }
191
        }
192
    }
193
}
194