├── _config.php
├── bin
├── test-env-setup
├── test
├── test-clean
├── test-test
└── test-build
├── _config
└── config.yml
├── .gitignore
├── code
├── ForgotPasswordSMTPEmail.php
├── SMTP_LogEmailWriter.php
├── SMTPEmail.php
└── SmtpMailer.php
├── .travis.yml
├── composer.json
├── README.md
└── tests
└── SMTPMailerTest.php
/_config.php:
--------------------------------------------------------------------------------
1 | subject = _t('Member.SUBJECTPASSWORDRESET', "Your password reset link", 'Email subject');
16 | }
17 | }
--------------------------------------------------------------------------------
/code/SMTP_LogEmailWriter.php:
--------------------------------------------------------------------------------
1 |
4 | * https://github.com/deanrather
5 | */
6 | class SMTP_LogEmailWriter extends SS_LogEmailWriter {
7 |
8 | /**
9 | * Send an email to the email address set in
10 | * this writer.
11 | */
12 | public function _write($event) {
13 | // If no formatter set up, use the default
14 | if(!$this->_formatter) {
15 | $formatter = new SS_LogErrorEmailFormatter();
16 | $this->setFormatter($formatter);
17 | }
18 |
19 | $formattedData = $this->_formatter->format($event);
20 | $subject = $formattedData['subject'];
21 | $data = $formattedData['data'];
22 |
23 | $email = new Email();
24 | $email->setTo($this->emailAddress);
25 | $email->setSubject($subject);
26 | $email->setBody($data);
27 | $email->setFrom(self::$send_from);
28 | $email->send();
29 | }
30 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - 5.4
4 | - 5.5
5 | - 5.6
6 | - 7.0
7 |
8 | env:
9 | matrix:
10 | - DB=MYSQL CORE_RELEASE=3.0
11 | - DB=MYSQL CORE_RELEASE=3.1
12 | - DB=MYSQL CORE_RELEASE=3.2
13 | - DB=MYSQL CORE_RELEASE=3.3
14 | - DB=MYSQL CORE_RELEASE=3.4
15 | - DB=MYSQL CORE_RELEASE=3.5
16 | - DB=MYSQL CORE_RELEASE=3.6
17 |
18 | matrix:
19 | allow_failures:
20 | - php: 7.0
21 | - php: 5.6
22 | env: DB=MYSQL CORE_RELEASE=master
23 | include:
24 | - php: 5.6
25 | env: DB=MYSQL CORE_RELEASE=master
26 | - php: 7.0
27 | env: DB=MYSQL CORE_RELEASE=master
28 |
29 | before_script:
30 | - phpenv rehash
31 | - composer self-update
32 | - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
33 | - php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss
34 | - cd ~/builds/ss
35 |
36 | script:
37 | - vendor/bin/phpunit abc-silverstripe-mailer/tests/
38 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "azt3k/abc-silverstripe-mailer",
3 | "description": "Library that adds smtp mail support to Silverstripe",
4 | "license": "BSD-3-Clause-Clear",
5 | "type": "silverstripe-module",
6 | "authors": [
7 | {
8 | "name": "Aaron Latham-Ilari",
9 | "email": "az@dev-io.us"
10 | }
11 | ],
12 | "minimum-stability": "dev",
13 | "require": {
14 | "php" : ">=5.3.0",
15 | "composer/installers" : ">=1.0",
16 | "silverstripe/framework" : "^3.0",
17 | "silverstripe/cms" : "^3.0",
18 | "phpmailer/phpmailer" : "~5.2.23"
19 | },
20 | "require-dev": {
21 | "phpunit/PHPUnit" : "~3.7",
22 | "silverstripe/sqlite3" : "*"
23 | },
24 | "extra": {
25 | "installer-paths": {
26 | "vendor/{$name}": [
27 | "phpmailer/phpmailer"
28 | ]
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/bin/test-build:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4 | DIR=~/builds/abc-silverstripe-mailer
5 |
6 | export TRAVIS_BRANCH=1.0
7 | export TRAVIS_COMMIT=HEAD
8 | export TRAVIS_REPO_SLUG=azt3k/abc-silverstripe-mailer
9 | export DB=SQLITE
10 | export CORE_RELEASE=3.1
11 |
12 | # get to the right place
13 | cd $PDIR/..
14 |
15 | # run the travis setup script
16 | mkdir -p $DIR
17 | git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git $DIR/travis-support
18 | php $DIR/travis-support/travis_setup.php --source $PDIR/.. --target $DIR/ss
19 |
20 | # make some mods to the project build
21 | mkdir $DIR/ss/silverstripe-cache
22 |
23 | # inject the autoloader
24 | # echo "
25 | # $DIR/ss/mysite/_config.php
40 |
41 | # apply patch
42 | # echo "
46 | # " | cat - $DIR/ss/framework/dev/SapphireTestReporter.php > /tmp/out && mv /tmp/out $DIR/ss/framework/dev/SapphireTestReporter.php
47 | sed -i "s/if(\!class_exists('PHPUnit_Framework_TestResult', false)) require_once 'PHPUnit\/Framework\/TestResult.php';/if (\!class_exists('PHPUnit_Framework_TestResult')) require_once 'PHPUnit\/Framework\/TestResult.php';/g" $DIR/ss/framework/dev/SapphireTestReporter.php
48 | sed -i "s/if(\!class_exists('PHPUnit_Framework_TestListener', false)) require_once 'PHPUnit\/Framework\/TestListener.php';/if (\!interface_exists('PHPUnit_Framework_TestListener')) require_once 'PHPUnit\/Framework\/TestListener.php';/g" $DIR/ss/framework/dev/SapphireTestReporter.php
49 |
50 | #sed -i "s/if(\!class_exists('PHPUnit_Framework_TestResult', false)) require_once 'PHPUnit\/Framework\/TestResult.php';/if (!class_exists('PHPUnit_Framework_TestResult')) require_once 'PHPUnit/Framework/TestResult.php';/g" ~/builds/abc-silverstripe-mailer/ss/framework/dev/SapphireTestReporter.php
51 |
52 |
53 | # "redeploy"
54 | rm -rf $DIR/ss/abc-silverstripe-mailer
55 | cp -rf $PDIR/.. $DIR/ss/abc-silverstripe-mailer
56 |
57 | bash $DIR/ss/framework/sake dev/build
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/azt3k/abc-silverstripe-mailer)
2 |
3 | Setup
4 | -----
5 |
6 | Add the following to you composer.json file:
7 |
8 | ```json
9 | "require": {
10 | "azt3k/abc-silverstripe-mailer" : "*@stable"
11 | }
12 | ```
13 |
14 | Add something like the following your `mysite/_config.php` file:
15 |
16 | ````php
17 | SmtpMailer::set_conf(array(
18 | 'default_from' => array(
19 | 'name' => 'admin',
20 | 'email' => 'admin@localhost'
21 | ),
22 | 'charset_encoding' => 'utf-8',
23 | 'server' => 'localhost',
24 | 'port' => 25,
25 | 'secure' => null,
26 | 'authenticate' => false,
27 | 'user' => 'username',
28 | 'pass' => 'password',
29 | 'debug' => 0,
30 | 'lang' => 'en'
31 | ));
32 | ````
33 | or
34 |
35 | ````php
36 | SmtpMailer::set_conf(array(
37 | 'default_from' => array(
38 | 'name' => 'user',
39 | 'email' => 'user@gmail.com'
40 | ),
41 | 'charset_encoding' => 'utf-8',
42 | 'server' => 'smtp.gmail.com',
43 | 'port' => 587,
44 | 'secure' => 'tls',
45 | 'authenticate' => true,
46 | 'user' => 'user@gmail.com',
47 | 'pass' => 'password',
48 | 'debug' => 0,
49 | 'lang' => 'en'
50 | ));
51 | ````
52 |
53 | Alternatively insert the configuration into your `project/_config/config.yml` file
54 |
55 | ````yaml
56 | SmtpMailer:
57 | conf:
58 | default_from:
59 | name: user
60 | email: user@gmail.com
61 | charset_encoding: utf-8
62 | server: smtp.gmail.com
63 | port: 587
64 | secure: tls
65 | authenticate: true
66 | user: user@gmail.com
67 | pass: password'
68 | debug: 0
69 | lang: en
70 | ````
71 |
72 |
73 | License
74 | -------
75 |
76 | Copyright (c) 2018 Aaron Latham-Ilari
77 |
78 | All rights reserved.
79 |
80 | Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:
81 |
82 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
83 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
84 | * Neither the name of [Owner Organization] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
85 |
86 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
87 |
88 |
--------------------------------------------------------------------------------
/code/SMTPEmail.php:
--------------------------------------------------------------------------------
1 | customHeaders;
11 | return !empty($h['Reply-To']) ? $h['Reply-To'] : null;
12 | }
13 |
14 | /**
15 | * makes ReplyTo work like BCC etc
16 | * @param [type] $val [description]
17 | */
18 | public function setReplyTo($val) {
19 | $this->addCustomHeader('Reply-To', $val);
20 | return $this;
21 | }
22 |
23 | /**
24 | * proxy method for file attachments
25 | * @param [type] $filename [description]
26 | * @param [type] $attachedFilename [description]
27 | * @param [type] $mimetype [description]
28 | * @return [type] [description]
29 | */
30 | public function attachFile($filename, $attachedFilename = null, $mimetype = null) {
31 |
32 | // generate a name for the file if we aren't supplied one
33 | if (!$attachedFilename) $attachedFilename = trim(str_replace(Director::baseFolder(), '', $filename), '/');
34 |
35 | // Get the full path
36 | if (!file_exists($filename)) $filename = Director::getAbsFile($filename);
37 |
38 | // try to attach the file
39 | if (file_exists($filename)) {
40 | $this->attachFileFromString(file_get_contents($filename), $attachedFilename, $mimetype);
41 | }
42 |
43 | // throw
44 | else {
45 | throw new Exception("Could not attach '$filename' to email. File does not exist.");
46 | }
47 |
48 | return $this;
49 | }
50 |
51 | public function Absolute($link) {
52 | return Director::protocolAndHost() . str_replace('//','/', '/' . $link);
53 | }
54 |
55 | /**
56 | * this is mainly a test harness
57 | * @return [type] [description]
58 | */
59 | public function setupMailer() {
60 |
61 | Requirements::clear();
62 |
63 | $this->parseVariables(true);
64 |
65 | if(empty($this->from)) $this->from = Email::config()->admin_email;
66 |
67 | $headers = $this->customHeaders;
68 |
69 | if(project()) $headers['X-SilverStripeSite'] = project();
70 |
71 | $to = $this->to;
72 | $from = $this->from;
73 | $subject = $this->subject;
74 | if ($sendAllTo = $this->config()->send_all_emails_to) {
75 | $subject .= " [addressed to $to";
76 | $to = $sendAllTo;
77 | if($this->cc) $subject .= ", cc to $this->cc";
78 | if($this->bcc) $subject .= ", bcc to $this->bcc";
79 | $subject .= ']';
80 | unset($headers['Cc']);
81 | unset($headers['Bcc']);
82 | } else {
83 | if($this->cc) $headers['Cc'] = $this->cc;
84 | if($this->bcc) $headers['Bcc'] = $this->bcc;
85 | }
86 |
87 | if ($ccAllTo = $this->config()->cc_all_emails_to) {
88 | if(!empty($headers['Cc']) && trim($headers['Cc'])) {
89 | $headers['Cc'] .= ', ' . $ccAllTo;
90 | } else {
91 | $headers['Cc'] = $ccAllTo;
92 | }
93 | }
94 |
95 | if ($bccAllTo = $this->config()->bcc_all_emails_to) {
96 | if(!empty($headers['Bcc']) && trim($headers['Bcc'])) {
97 | $headers['Bcc'] .= ', ' . $bccAllTo;
98 | } else {
99 | $headers['Bcc'] = $bccAllTo;
100 | }
101 | }
102 |
103 | if ($sendAllfrom = $this->config()->send_all_emails_from) {
104 | if($from) $subject .= " [from $from]";
105 | $from = $sendAllfrom;
106 | }
107 |
108 | Requirements::restore();
109 |
110 | return self::mailer()->setupMailer($to, $from, $subject, $this->attachments, $headers);
111 |
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/tests/SMTPMailerTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('SmtpMailer', get_class($mailer));
13 |
14 | $mailer = SMTPEmail::mailer();
15 | $this->assertEquals('SmtpMailer', get_class($mailer));
16 | }
17 |
18 | /**
19 | * @depends testSetup
20 | */
21 | public function testSMTPMailerSetConf() {
22 |
23 | // phpunit is a bit broken so we manually call the dependent tests;
24 | $this->testSetup();
25 |
26 | $conf_in = array(
27 | 'default_from' => array(
28 | 'name' => 'abc-silverstripe-mailer-from',
29 | 'email' => 'abc-silverstripe-mailer-from@mailinator.com'
30 | ),
31 | 'charset_encoding' => 'utf-8',
32 | 'server' => 'mail.mailinator.com',
33 | 'port' => 25,
34 | 'secure' => null,
35 | 'authenticate' => false,
36 | 'user' => '',
37 | 'pass' => '',
38 | 'debug' => 0,
39 | 'lang' => 'en'
40 | );
41 |
42 | SMTPMailer::set_conf($conf_in);
43 |
44 | $conf_out = (array) SMTPMailer::get_conf();
45 |
46 | $this->assertEquals($conf_in, $conf_out);
47 | }
48 |
49 | /**
50 | * @depends testSMTPMailerSetConf
51 | */
52 | public function testEmail() {
53 |
54 | // phpunit is a bit broken so we manually call the dependent tests;
55 | $this->testSMTPMailerSetConf();
56 |
57 | $e = new Email();
58 | $e->To = "abc-silverstripe-mailer@mailinator.com";
59 | $e->Subject = "Hi there";
60 | $e->Body = "I just really wanted to email you and say hi.";
61 |
62 | $this->assertEquals(true, $e->send());
63 |
64 | }
65 |
66 | /**
67 | * @depends testSMTPMailerSetConf
68 | */
69 | public function testSMTPEmail() {
70 |
71 | // phpunit is a bit broken so we manually call the dependent tests;
72 | $this->testSMTPMailerSetConf();
73 |
74 | $e = new SMTPEmail();
75 | $e->To = "abc-silverstripe-mailer@mailinator.com";
76 | $e->Subject = "Hi there";
77 | $e->Body = "I just really wanted to email you and say hi.";
78 |
79 | $this->assertEquals(true, $e->send());
80 |
81 | }
82 |
83 | // disabling this test because Email Doesn't come out as SMTP email in these tests
84 | // /**
85 | // * @depends testEmail
86 | // */
87 | // public function testEmailCustomHeaders() {
88 | //
89 | // // phpunit is a bit broken so we manually call the dependent tests;
90 | // $this->testEmail();
91 | //
92 | // $bcc = "abc-silverstripe-mailer-bcc@mailinator.com";
93 | // $cc = "abc-silverstripe-mailer-cc@mailinator.com";
94 | // $replyto = "abc-silverstripe-mailer-reply-to@mailinator.com";
95 | //
96 | // $e = new Email();
97 | // $e->To = "abc-silverstripe-mailer@mailinator.com";
98 | // $e->Subject = "Hi there";
99 | // $e->Body = "I just really wanted to email you and say hi.";
100 | // $e->Cc = $cc;
101 | // $e->Bcc = $bcc;
102 | // $e->ReplyTo = $replyto;
103 | //
104 | // // get the mailer bound to the Email class
105 | // $e->setupMailer();
106 | // $mailer = Email::mailer()->mailer;
107 | //
108 | // // check bccs
109 | // $bccs = $mailer->getBccAddresses();
110 | // $this->assertEquals(true, in_array($bcc, $bccs));
111 | //
112 | // // check ccs
113 | // $ccs = $mailer->getCcAddresses();
114 | // $this->assertEquals(true, in_array($cc, $ccs));
115 | //
116 | // // check replytos
117 | // $replytos = $mailer->getReplyToAddresses();
118 | // $this->assertEquals(true, in_array($reployto, $reploytos));
119 | //
120 | // // check send
121 | // // $this->assertEquals(true, $e->send());
122 | //
123 | // }
124 |
125 | /**
126 | * @depends testSMTPEmail
127 | */
128 | public function testSMTPEmailCustomHeaders()
129 | {
130 |
131 | // phpunit is a bit broken so we manually call the dependent tests;
132 | $this->testSMTPEmail();
133 |
134 | $bcc = "abc-silverstripe-mailer-bcc@mailinator.com";
135 | $cc = "abc-silverstripe-mailer-cc@mailinator.com";
136 | $replyto = "abc-silverstripe-mailer-reply-to@mailinator.com";
137 |
138 | $e = new SMTPEmail();
139 | $e->To = "abc-silverstripe-mailer@mailinator.com";
140 | $e->Subject = "Hi there";
141 | $e->Body = "I just really wanted to email you and say hi.";
142 | $e->Cc = $cc;
143 | $e->Bcc = $bcc;
144 | $e->ReplyTo = $replyto;
145 |
146 | // get the mailer bound to the Email class
147 | $e->setupMailer();
148 | $mailer = SMTPEmail::mailer()->mailer;
149 |
150 | // check bccs
151 | $bccs = $mailer->getBccAddresses();
152 | $exists = false;
153 | foreach ($bccs as $item) {
154 | if (in_array($bcc, $item)) $exists = true;
155 | }
156 | $this->assertEquals(true, $exists);
157 |
158 | // check ccs
159 | $ccs = $mailer->getCcAddresses();
160 | $exists = false;
161 | foreach ($ccs as $item) {
162 | if (in_array($cc, $item)) $exists = true;
163 | }
164 | $this->assertEquals(true, $exists);
165 |
166 | // check replytos
167 | $replytos = $mailer->getReplyToAddresses();
168 | $exists = false;
169 | foreach ($replytos as $item) {
170 | if (in_array($replyto, $item)) $exists = true;
171 | }
172 | $this->assertEquals(true, $exists);
173 |
174 | // check send
175 | $this->assertEquals(true, $e->send());
176 |
177 | }
178 |
179 | /**
180 | * @depends testSMTPEmailCustomHeaders
181 | */
182 | public function testMultipleRecipients() {
183 |
184 | // phpunit is a bit broken so we manually call the dependent tests;
185 | $this->testSMTPEmailCustomHeaders();
186 |
187 | $to = 'abc-silverstripe-mailer@mailinator.com';
188 | $to2 = 'abc-silverstripe-mailer-2@mailinator.com';
189 |
190 | $e = new SMTPEmail();
191 | $e->To = $to . ', ' . $to2;
192 | $e->Subject = "Hi there";
193 | $e->Body = "I just really wanted to email you and say hi.";
194 |
195 | // get the mailer bound to the Email class
196 | $e->setupMailer();
197 | $mailer = SMTPEmail::mailer()->mailer;
198 |
199 | // check recipients
200 | $tos = $mailer->getToAddresses();
201 | $exists = $exists2 = false;
202 | foreach ($tos as $item) {
203 | if (in_array($to, $item)) $exists = true;
204 | if (in_array($to2, $item)) $exists2 = true;
205 | }
206 | $this->assertEquals(true, $exists && $exists2);
207 |
208 | // check send
209 | $this->assertEquals(true, $e->send());
210 |
211 | }
212 |
213 | /**
214 | * @depends testSMTPEmail
215 | */
216 | public function testFSAttachmentEmail() {
217 |
218 | // phpunit is a bit broken so we manually call the dependent tests;
219 | $this->testSMTPEmail();
220 |
221 | // create file
222 | $fileContents = 'test content';
223 | $fileName = 'test.txt';
224 | $type = 'text/plain';
225 | $absFileName = sys_get_temp_dir() . '/' . $fileName;
226 | file_put_contents($absFileName, $fileContents);
227 |
228 | // create email
229 | $e = new SMTPEmail();
230 | $e->To = 'abc-silverstripe-mailer@mailinator.com';
231 | $e->Subject = "Hi there";
232 | $e->Body = "I just really wanted to email you and say hi.";
233 | $e->attachFile($absFileName, $fileName, $type);
234 |
235 | // get the mailer bound to the Email class
236 | $e->setupMailer();
237 | $mailer = SMTPEmail::mailer()->mailer;
238 |
239 | // check attached files
240 | $files = $mailer->getAttachments();
241 | $this->assertEquals(true, $files[0][0] == $fileContents);
242 | $this->assertEquals(true, $files[0][1] == $fileName);
243 | $this->assertEquals(true, $files[0][4] == $type);
244 |
245 | // check send
246 | $this->assertEquals(true, $e->send());
247 |
248 | }
249 |
250 | /**
251 | * @depends testSMTPEmail
252 | */
253 | public function testStringAttachmentEmail() {
254 |
255 | // phpunit is a bit broken so we manually call the dependent tests;
256 | $this->testSMTPEmail();
257 |
258 | // create file
259 | $fileContents = 'test content 2';
260 | $fileName = 'test2.txt';
261 | $type = 'text/plain';
262 |
263 | // create email
264 | $e = new SMTPEmail();
265 | $e->To = 'abc-silverstripe-mailer@mailinator.com';
266 | $e->Subject = "Hi there";
267 | $e->Body = "I just really wanted to email you and say hi.";
268 | $e->attachFileFromString($fileContents, $fileName, $type);
269 |
270 | // get the mailer bound to the Email class
271 | $e->setupMailer();
272 | $mailer = SMTPEmail::mailer()->mailer;
273 |
274 | // check attached files
275 | $files = $mailer->getAttachments();
276 | $this->assertEquals(true, $files[0][0] == $fileContents);
277 | $this->assertEquals(true, $files[0][1] == $fileName);
278 | $this->assertEquals(true, $files[0][4] == $type);
279 |
280 | // check send
281 | $this->assertEquals(true, $e->send());
282 |
283 | }
284 |
285 | /**
286 | * @depends testSMTPEmail
287 | */
288 | public function testForgotPasswordEmail() {
289 |
290 | // phpunit is a bit broken so we manually call the dependent tests;
291 | $this->testSMTPEmail();
292 |
293 | $e = new ForgotPasswordSMTPEmail();
294 |
295 | $this->assertEquals('ForgotPasswordEmail', $e->ss_template);
296 | }
297 |
298 | /**
299 | * @depends testForgotPasswordEmail
300 | */
301 | public function testForgotPasswordSend() {
302 |
303 | // phpunit is a bit broken so we manually call the dependent tests;
304 | $this->testForgotPasswordEmail();
305 |
306 | $data = Array (
307 | 'FirstName' => 'John',
308 | 'PasswordResetLink' => '/reset-link-123',
309 | 'AbsoluteBaseURL' => 'www.silverstripe.com'
310 | );
311 |
312 | $to = 'abc@silverstripe.co.nz';
313 |
314 | $e = Member_ForgotPasswordEmail::create();
315 | $e->populateTemplate($data);
316 | $e->setTo($to);
317 |
318 | $this->assertEquals(true, $e->send());
319 | }
320 |
321 | }
322 |
--------------------------------------------------------------------------------
/code/SmtpMailer.php:
--------------------------------------------------------------------------------
1 | array(
9 | 'name' => 'admin',
10 | 'email' => 'admin@localhost'
11 | ),
12 | 'charset_encoding' => 'utf-8',
13 | 'server' => 'localhost',
14 | 'port' => 25,
15 | 'secure' => null,
16 | 'authenticate' => false,
17 | 'user' => '',
18 | 'pass' => '',
19 | 'debug' => 0,
20 | 'lang' => 'en'
21 | );
22 |
23 | /**
24 | * @config
25 | */
26 | private static $conf = array();
27 |
28 | /**
29 | * Constructor
30 | *
31 | * @param Mailer $mailer
32 | */
33 | public function __construct($mailer = null) {
34 | $this->mailer = $mailer;
35 | }
36 |
37 | /**
38 | * @param array|object $conf An associative array containing the configuration - see static::$conf for an example
39 | * @return void
40 | */
41 | public static function set_conf($conf) {
42 | $conf = (array) $conf;
43 | static::$conf = static::array_merge_recursive_distinct(static::$conf, $conf);
44 | }
45 |
46 | /**
47 | * @return stdClass
48 | */
49 | public static function get_conf() {
50 | return (object) static::array_merge_recursive_distinct(static::$defaults, static::$conf);
51 | }
52 |
53 | /**
54 | * @return void
55 | */
56 | protected static function set_conf_from_yaml() {
57 | $conf = (array) Config::inst()->get('SmtpMailer', 'conf');
58 | // die(print_r($conf,1));
59 | if (!empty($conf))
60 | static::$conf = static::array_merge_recursive_distinct(static::$conf, $conf);
61 | }
62 |
63 | /**
64 | * @return void
65 | */
66 | public function configure() {
67 |
68 | // configure from YAML if available
69 | static::set_conf_from_yaml();
70 |
71 | // get the configuration
72 | $conf = static::get_conf();
73 |
74 | if (!$this->mailer) {
75 |
76 | // configure PHP mailer
77 | $this->mailer = new PHPMailer(true);
78 | $this->mailer->IsSMTP();
79 | $this->mailer->CharSet = $conf->charset_encoding;
80 | $this->mailer->Host = $conf->server;
81 | $this->mailer->Port = $conf->port;
82 | $this->mailer->SMTPSecure = $conf->secure;
83 | $this->mailer->SMTPAuth = $conf->authenticate;
84 | $this->mailer->SMTPDebug = $conf->debug;
85 | $this->mailer->SetLanguage($conf->lang);
86 |
87 | // auth?
88 | if ($this->mailer->SMTPAuth) {
89 | $this->mailer->Username = $conf->user;
90 | $this->mailer->Password = $conf->pass;
91 | }
92 | }
93 |
94 | // chain me
95 | return $this;
96 | }
97 |
98 | /**
99 | * Overwriting Mailer's function
100 | *
101 | * @param string $to the recipient
102 | * @param string $from the sender
103 | * @param string $subject the subject
104 | * @param string $plainContent plain text content
105 | * @param array $attachedFiles an array of files to attach
106 | * @param array $customheaders an array of custom headers to attach
107 | * @return boolean
108 | */
109 | public function sendPlain($to, $from, $subject, $plainContent, $attachedFiles = array(), $customheaders = false) {
110 | $this->configure();
111 | $this->mailer->IsHTML( false );
112 | $this->mailer->Body = $plainContent;
113 | return $this->sendMailViaSmtp( $to, $from, $subject, $attachedFiles, $customheaders, false );
114 | }
115 |
116 |
117 | /**
118 | * Overwriting Mailer's function
119 | *
120 | * @param string $to the recipient
121 | * @param string $from the sender
122 | * @param string $subject the subject
123 | * @param string $htmlContent html content
124 | * @param array $attachedFiles an array of files to attach
125 | * @param array $customheaders an array of custom headers to attach
126 | * @param string $plainContent plaintext alternative
127 | * @param array $inlineImages an array of image files to attach inline
128 | * @return boolean
129 | */
130 | public function sendHTML(
131 | $to,
132 | $from,
133 | $subject,
134 | $htmlContent,
135 | $attachedFiles = array(),
136 | $customheaders = false,
137 | $plainContent = false,
138 | $inlineImages = false
139 | ) {
140 |
141 | $this->configure();
142 | $this->mailer->IsHTML(true);
143 |
144 | if ($inlineImages) {
145 | $this->mailer->MsgHTML($htmlContent, Director::baseFolder());
146 | }
147 | else {
148 | $this->mailer->Body = $htmlContent;
149 | if (empty($plainContent)) $plainContent = trim(Convert::html2raw($htmlContent));
150 | $this->mailer->AltBody = $plainContent;
151 | }
152 |
153 | return $this->sendMailViaSmtp($to, $from, $subject, $attachedFiles, $customheaders, $inlineImages);
154 | }
155 |
156 | /**
157 | * @param string $to the recipient
158 | * @param string $from the sender
159 | * @param string $subject the subject
160 | * @param array $attachedFiles an array of files to attach
161 | * @param array $customheaders an array of custom headers to attach
162 | * @param array $inlineImages an array of image files to attach inline
163 | * @return boolean
164 | */
165 | public function setupMailer($to, $from, $subject, $attachedFiles = array(), $customheaders = false) {
166 |
167 | // init this for later if we need it
168 | $msgForLog = '';
169 |
170 | // make sure we have a mailer
171 | if (!$this->mailer) $this->configure();
172 |
173 | // default result
174 | $result = false;
175 |
176 | // default from
177 | if (!$from) $from = static::$conf['default_from']['email'];
178 |
179 | // try to update stuff
180 | try {
181 |
182 | $this->buildBasicMail($to, $from, $subject);
183 | $this->addCustomHeaders($customheaders);
184 | $this->attachFiles((array) $attachedFiles);
185 | $result = true;
186 |
187 | }
188 | catch (phpmailerException $e) {
189 | $this->handleError($e->errorMessage(), $msgForLog);
190 | }
191 | catch (Exception $e) {
192 | $this->handleError($e->getMessage(), $msgForLog);
193 | }
194 |
195 | return $result;
196 | }
197 |
198 | /**
199 | * @param string $to the recipient
200 | * @param string $from the sender
201 | * @param string $subject the subject
202 | * @param array $attachedFiles an array of files to attach
203 | * @param array $customheaders an array of custom headers to attach
204 | * @param array $inlineImages an array of image files to attach inline
205 | * @return boolean
206 | */
207 | protected function sendMailViaSmtp(
208 | $to,
209 | $from,
210 | $subject,
211 | $attachedFiles = array(),
212 | $customheaders = false,
213 | $inlineImages = false
214 | ) {
215 |
216 | // default result
217 | $result = false;
218 |
219 | if ($this->mailer->SMTPDebug > 0)
220 | echo "*** Debug mode is on, printing debug messages and not redirecting to the website:
";
221 |
222 | $msgForLog = "\n*** The sender was : $from\n*** The message was :\n{$this->mailer->AltBody}\n";
223 |
224 | try {
225 |
226 | // try to send
227 | if ($this->setupMailer($to, $from, $subject, $attachedFiles, $customheaders))
228 | $result = $this->mailer->send();
229 |
230 | if ($this->mailer->SMTPDebug > 0) {
231 | echo "*** E-mail to $to has been sent.
";
232 | echo "*** The debug mode blocked the process to avoid the url redirection. So the CC e-mail is not sent.";
233 | }
234 |
235 | }
236 | catch(phpmailerException $e) {
237 | $this->handleError($e->errorMessage(), $msgForLog);
238 | }
239 | catch(Exception $e) {
240 | $this->handleError($e->getMessage(), $msgForLog);
241 | }
242 |
243 | return $result;
244 | }
245 |
246 | /**
247 | * @param string $e The error message - usually Exception::errorMessage()
248 | * @param string $msgForLog The message for the SS log
249 | * @param return void
250 | */
251 | public function handleError($e, $msgForLog) {
252 | $msg = $e . $msgForLog;
253 | SS_Log::log($msg, Zend_Log::ERR);
254 | throw new Exception($msg);
255 | }
256 |
257 | /**
258 | * @param string $to
259 | * @param string $from
260 | * @param string $subject
261 | * @return void
262 | */
263 | protected function buildBasicMail($to, $from, $subject) {
264 |
265 | if (preg_match('/(\'|")(.*?)\1[ ]+<[ ]*(.*?)[ ]*>/', $from, $from_split)) {
266 | // If $from countain a name, e.g. "My Name"
267 | $this->mailer->SetFrom( $from_split[3], $from_split[2] );
268 | }
269 | else {
270 | $this->mailer->SetFrom( $from );
271 | }
272 |
273 | // set subject
274 | $this->mailer->Subject = $subject;
275 |
276 | // clear addresses
277 | $this->mailer->ClearAddresses();
278 |
279 | // clear attachments
280 | $this->mailer->ClearAttachments();
281 |
282 | // split addresses
283 | $tos = explode(',', $to);
284 |
285 | // add addresses
286 | foreach ($tos as $addr) {
287 |
288 | // clean
289 | $addr = trim($addr);
290 |
291 | // validate
292 | // if (Email::validEmailAddress($addr)) {
293 |
294 | // For the recipient's name, the string before the @ from the e-mail address is used
295 | // this doesn't support the "Mr Nobody " syntax
296 | $this->mailer->AddAddress($addr, ucfirst(substr($addr, 0, strpos( $addr, '@' ))));
297 | // }
298 | }
299 |
300 | }
301 |
302 | /**
303 | * @param array $headers
304 | * @return void
305 | */
306 | protected function addCustomHeaders( $headers ) {
307 |
308 | if( !$headers or !is_array($headers) ) $headers = array();
309 | if( !isset( $headers["X-Mailer"] ) ) $headers["X-Mailer"] = X_MAILER;
310 | if( !isset( $headers["X-Priority"] ) ) $headers["X-Priority"] = 3;
311 |
312 | // clear existing headers
313 | $this->mailer->ClearCustomHeaders();
314 |
315 | // look at all the headers and handle appropriately
316 | foreach ($headers as $header_name => $header_value) {
317 |
318 | // split
319 | if (in_array(strtolower($header_name), array('cc', 'bcc', 'reply-to', 'replyto')))
320 | $addresses = preg_split('/(,|;)/', $header_value);
321 |
322 | // call setters rather than setting headers for:
323 | // - bcc
324 | // - cc
325 | // - reply-to
326 | switch (strtolower($header_name)) {
327 | case 'cc':
328 | foreach ($addresses as $address) {
329 | $this->mailer->addCC($address);
330 | }
331 | break;
332 | case 'bcc':
333 | foreach ($addresses as $address) {
334 | $this->mailer->addBCC($address);
335 | }
336 | break;
337 | case 'reply-to':
338 | case 'replyto':
339 | foreach ($addresses as $address) {
340 | $this->mailer->addReplyTo($address);
341 | }
342 | break;
343 | default:
344 | $this->mailer->AddCustomHeader($header_name . ':' . $header_value);
345 | break;
346 | }
347 | }
348 | }
349 |
350 | /**
351 | * @param array $attachedFiles
352 | * @return void
353 | */
354 | protected function attachFiles(array $attachedFiles) {
355 | if (!empty($attachedFiles) && is_array($attachedFiles)) {
356 | foreach ($attachedFiles as $attachedFile) {
357 |
358 | // all attached files are stashed as strings in the attached files array
359 | // see Email and SMTPEMail classes for more info
360 | $this->mailer->AddStringAttachment(
361 | $attachedFile['contents'],
362 | $attachedFile['filename'],
363 | 'base64',
364 | $attachedFile['mimetype']
365 | );
366 | }
367 | }
368 | }
369 |
370 | /**
371 | * @param array $array1 The first array
372 | * @param array $array2 The second array
373 | * @return array the merged array
374 | */
375 | protected static function array_merge_recursive_distinct( array $array1, array $array2 ) {
376 |
377 | $merged = $array1;
378 |
379 | foreach ($array2 as $key => $value) {
380 |
381 | if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
382 | $merged[$key] = static::array_merge_recursive_distinct($merged[$key], $value);
383 | }
384 | else {
385 | $merged[$key] = $value;
386 | }
387 | }
388 |
389 | return $merged;
390 | }
391 |
392 | }
393 |
--------------------------------------------------------------------------------