Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
Mailer
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
9 / 9
22
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 transport
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setDefaultFrom
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getDefaultFrom
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasDefaultFrom
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 send
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 sendFromQueue
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 sendFromDir
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
7
 dispatch
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Mail;
16
17use Pop\Mail\Transport\TransportInterface;
18
19/**
20 * Mailer class
21 *
22 * @category   Pop
23 * @package    Pop\Mail
24 * @author     Nick Sagona, III <nick@popphp.org>
25 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
26 * @license    https://www.popphp.org/license     New BSD License
27 * @version    5.0.0
28 */
29class Mailer
30{
31
32    /**
33     * Transport object
34     * @var ?TransportInterface
35     */
36    protected ?TransportInterface $transport = null;
37
38
39    /**
40     * Default from address
41     * @var ?string
42     */
43    protected ?string $defaultFrom = null;
44
45    /**
46     * Constructor
47     *
48     * Instantiate the message object
49     *
50     * @param TransportInterface $transport
51     * @param ?string            $defaultFrom
52     */
53    public function __construct(TransportInterface $transport, ?string $defaultFrom = null)
54    {
55        $this->transport   = $transport;
56        $this->defaultFrom = $defaultFrom;
57    }
58
59    /**
60     * Get the transport object
61     *
62     * @return TransportInterface
63     */
64    public function transport(): TransportInterface
65    {
66        return $this->transport;
67    }
68
69    /**
70     * Set default from address
71     *
72     * @param  string $from
73     * @return Mailer
74     */
75    public function setDefaultFrom(string $from): Mailer
76    {
77        $this->defaultFrom = $from;
78        return $this;
79    }
80
81    /**
82     * Get default from address
83     *
84     * @return ?string
85     */
86    public function getDefaultFrom(): ?string
87    {
88        return $this->defaultFrom;
89    }
90
91    /**
92     * Has default from address
93     *
94     * @return bool
95     */
96    public function hasDefaultFrom(): bool
97    {
98        return ($this->defaultFrom !== null);
99    }
100
101    /**
102     * Send message
103     *
104     * @param  Message $message
105     * @return mixed
106     */
107    public function send(Message $message): mixed
108    {
109        if ((!$message->hasFrom()) && ($this->hasDefaultFrom())) {
110            $message->setFrom($this->defaultFrom);
111        }
112
113        return $this->transport->send($message);
114    }
115
116    /**
117     * Send messages from mail queue
118     *
119     * If the transport implements BatchTransportInterface, all prepared
120     * messages are handed to it in one call instead of being sent one at a
121     * time, so batch-capable transports can use their provider's native
122     * bulk-send endpoint.
123     *
124     * @param  Queue $queue
125     * @return int
126     */
127    public function sendFromQueue(Queue $queue): int
128    {
129        $messages = $queue->prepare();
130
131        foreach ($messages as $message) {
132            if ((!$message->hasFrom()) && ($this->hasDefaultFrom())) {
133                $message->setFrom($this->defaultFrom);
134            }
135        }
136
137        return $this->dispatch($messages);
138    }
139
140    /**
141     * Send messages from email messages saved to disk in a directory
142     *
143     * If the transport implements BatchTransportInterface, all loaded
144     * messages are handed to it in one call instead of being sent one at a
145     * time (see sendFromQueue()).
146     *
147     * @param  string $dir
148     * @throws Exception
149     * @return int
150     */
151    public function sendFromDir(string $dir): int
152    {
153        if (!file_exists($dir)) {
154            throw new Exception('Error: That directory does not exist');
155        }
156
157        $files = array_filter(scandir($dir), function($value) {
158            return (($value != '.') && ($value != '..') && ($value != '.empty'));
159        });
160
161        $messages = [];
162        foreach ($files as $file) {
163            $message = Message::load($dir . DIRECTORY_SEPARATOR . $file);
164
165            if ((!$message->hasFrom()) && ($this->hasDefaultFrom())) {
166                $message->setFrom($this->defaultFrom);
167            }
168
169            $messages[] = $message;
170        }
171
172        return $this->dispatch($messages);
173    }
174
175    /**
176     * Send a batch of already-prepared messages, preferring the transport's
177     * native batch API when it supports one
178     *
179     * @param  Message[] $messages
180     * @return int
181     */
182    private function dispatch(array $messages): int
183    {
184        if ($this->transport instanceof Transport\BatchTransportInterface) {
185            return $this->transport->sendBatch($messages);
186        }
187
188        $sent = 0;
189        foreach ($messages as $message) {
190            $this->transport->send($message);
191            $sent++;
192        }
193
194        return $sent;
195    }
196
197}