<?php
/**
* PHPMailer - PHP email transport unit tests.
* PHP version 5.5.
*
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
* @author Andy Prevost
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace PHPMailer\Test\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\Test\SendTestCase;
final class PHPMailerTest extends SendTestCase
{
private $Smtp;
public function testLowPriority()
{
$this->Mail->Priority = 5;
$this->Mail->Body = 'Here is the main body. There should be ' .
'a reply to address in this message.';
$this->Mail->Subject .= ': Low Priority';
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testMultiplePlainFileAttachment()
{
$this->Mail->Body = 'Here is the text body';
$this->Mail->Subject .= ': Plain + Multiple FileAttachments';
if (!$this->Mail->addAttachment(realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer.png'))) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
if (!$this->Mail->addAttachment(__FILE__, 'test.txt')) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testRejectNonLocalFileAttachment()
{
self::assertFalse(
$this->Mail->addAttachment('https://github.com/PHPMailer/PHPMailer/raw/master/README.md'),
'addAttachment should reject remote URLs'
);
self::assertFalse(
$this->Mail->addAttachment('phar://phar.php'),
'addAttachment should reject phar resources'
);
}
public function testQuotedPrintable()
{
$this->Mail->Body = 'Here is the main body';
$this->Mail->Subject .= ': Plain + Quoted-printable';
$this->Mail->Encoding = 'quoted-printable';
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$t = file_get_contents(__FILE__); $t = str_replace(["\r\n", "\r"], "\n", $t);
self::assertSame(
$t,
quoted_printable_decode($this->Mail->encodeQP($t)),
'Quoted-Printable encoding round-trip failed'
);
$t = str_replace("\n", "\r\n", $t);
self::assertSame(
$t,
quoted_printable_decode($this->Mail->encodeQP($t)),
'Quoted-Printable encoding round-trip failed (Windows line breaks)'
);
}
public function testHeaderEncoding()
{
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
$letter = html_entity_decode('é', ENT_COMPAT, PHPMailer::CHARSET_UTF8);
$bencode = str_repeat($letter, PHPMailer::STD_LINE_LENGTH + 1);
$qencode = str_repeat('e', PHPMailer::STD_LINE_LENGTH) . $letter;
$bencodenofold = str_repeat($letter, 10);
$qencodenofold = str_repeat('e', 9) . $letter;
$longheader = str_repeat('e', PHPMailer::STD_LINE_LENGTH + 10);
$longutf8 = str_repeat($letter, PHPMailer::STD_LINE_LENGTH + 10);
$noencode = 'eeeeeeeeee';
$this->Mail->isMail();
$bencoderes = '=?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' .
PHPMailer::getLE() .
' =?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' .
PHPMailer::getLE() .
' =?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' .
PHPMailer::getLE() .
' =?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqQ==?=';
$qencoderes = '=?utf-8?Q?eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee?=' .
PHPMailer::getLE() .
' =?utf-8?Q?eeeeeeeeeeeeeeeeeeeeeeeeee=C3=A9?=';
$bencodenofoldres = '=?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6k=?=';
$qencodenofoldres = '=?utf-8?Q?eeeeeeeee=C3=A9?=';
$longheaderres = '=?us-ascii?Q?eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee?=' .
PHPMailer::getLE() . ' =?us-ascii?Q?eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee?=';
$longutf8res = '=?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' .
PHPMailer::getLE() . ' =?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' .
PHPMailer::getLE() . ' =?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' .
PHPMailer::getLE() . ' =?utf-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqQ==?=';
$noencoderes = 'eeeeeeeeee';
self::assertSame(
$bencoderes,
$this->Mail->encodeHeader($bencode),
'Folded B-encoded header value incorrect'
);
self::assertSame(
$qencoderes,
$this->Mail->encodeHeader($qencode),
'Folded Q-encoded header value incorrect'
);
self::assertSame(
$bencodenofoldres,
$this->Mail->encodeHeader($bencodenofold),
'B-encoded header value incorrect'
);
self::assertSame(
$qencodenofoldres,
$this->Mail->encodeHeader($qencodenofold),
'Q-encoded header value incorrect'
);
self::assertSame(
$longheaderres,
$this->Mail->encodeHeader($longheader),
'Long header value incorrect'
);
self::assertSame(
$longutf8res,
$this->Mail->encodeHeader($longutf8),
'Long UTF-8 header value incorrect'
);
self::assertSame(
$noencoderes,
$this->Mail->encodeHeader($noencode),
'Unencoded header value incorrect'
);
}
public function testHtml()
{
$this->Mail->isHTML(true);
$this->Mail->Subject .= ': HTML only';
$this->Mail->Body = <<<'EOT'
<!DOCTYPE html>
<html lang="en">
<head>
<title>HTML email test</title>
</head>
<body>
<h1>PHPMailer does HTML!</h1>
<p>This is a <strong>test message</strong> written in HTML.<br>
Go to <a href="https://github.com/PHPMailer/PHPMailer/">https://github.com/PHPMailer/PHPMailer/</a>
for new versions of PHPMailer.</p>
<p>Thank you!</p>
</body>
</html>
EOT;
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$msg = $this->Mail->getSentMIMEMessage();
self::assertStringNotContainsString("\r\n\r\nMIME-Version:", $msg, 'Incorrect MIME headers');
}
public function testDsn()
{
$this->Mail->isHTML(true);
$this->Mail->Subject .= ': HTML only';
$this->Mail->Body = <<<'EOT'
<!DOCTYPE html>
<html lang="en">
<head>
<title>HTML email test</title>
</head>
<body>
<p>PHPMailer</p>
</body>
</html>
EOT;
$this->buildBody();
$this->Mail->dsn = 'SUCCESS,FAILURE';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->dsn = 'NEVER';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testCreateBody()
{
$PHPMailer = new PHPMailer();
$reflection = new \ReflectionClass($PHPMailer);
$property = $reflection->getProperty('message_type');
$property->setAccessible(true);
$property->setValue($PHPMailer, 'inline');
self::assertIsString($PHPMailer->createBody());
$property->setValue($PHPMailer, 'attach');
self::assertIsString($PHPMailer->createBody());
$property->setValue($PHPMailer, 'inline_attach');
self::assertIsString($PHPMailer->createBody());
$property->setValue($PHPMailer, 'alt');
self::assertIsString($PHPMailer->createBody());
$property->setValue($PHPMailer, 'alt_inline');
self::assertIsString($PHPMailer->createBody());
$property->setValue($PHPMailer, 'alt_attach');
self::assertIsString($PHPMailer->createBody());
$property->setValue($PHPMailer, 'alt_inline_attach');
self::assertIsString($PHPMailer->createBody());
}
public function testHtmlIso8859()
{
$this->Mail->isHTML(true);
$this->Mail->Subject .= ': ISO-8859-1 HTML';
$this->Mail->CharSet = PHPMailer::CHARSET_ISO88591;
$content = file_get_contents(realpath(\PHPMAILER_INCLUDE_DIR . '/examples/contents.html'));
$check = base64_decode('6eju/OfF8ebf');
$this->Mail->msgHTML(
mb_convert_encoding(
$content,
'ISO-8859-1',
mb_detect_encoding($content, 'UTF-8, ISO-8859-1, ISO-8859-15', true)
),
realpath(\PHPMAILER_INCLUDE_DIR . '/examples')
);
$this->buildBody();
self::assertStringContainsString($check, $this->Mail->Body, 'ISO message body does not contain expected text');
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testHtmlUtf8()
{
$this->Mail->isHTML(true);
$this->Mail->Subject .= ': UTF-8 HTML Пустое тело сообщения';
$this->Mail->CharSet = 'UTF-8';
$this->Mail->Body = <<<'EOT'
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>HTML email test</title>
</head>
<body>
<p>Chinese text: 郵件內容為空</p>
<p>Russian text: Пустое тело сообщения</p>
<p>Armenian text: Հաղորդագրությունը դատարկ է</p>
<p>Czech text: Prázdné tělo zprávy</p>
</body>
</html>
EOT;
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$msg = $this->Mail->getSentMIMEMessage();
self::assertStringNotContainsString("\r\n\r\nMIME-Version:", $msg, 'Incorrect MIME headers');
}
public function testUtf8WithEmbeddedImage()
{
$this->Mail->isHTML(true);
$this->Mail->Subject .= ': UTF-8 with embedded image';
$this->Mail->CharSet = 'UTF-8';
$this->Mail->Body = <<<'EOT'
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>HTML email test</title>
</head>
<body>
<p>Chinese text: 郵件內容為空</p>
<p>Russian text: Пустое тело сообщения</p>
<p>Armenian text: Հաղորդագրությունը դատարկ է</p>
<p>Czech text: Prázdné tělo zprávy</p>
Embedded Image: <img alt="phpmailer" src="cid:bäck">
</body>
</html>
EOT;
$this->Mail->addEmbeddedImage(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer.png'),
'bäck',
'phpmailer.png',
'base64',
'image/png'
);
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testPlainUtf8()
{
$this->Mail->isHTML(false);
$this->Mail->Subject .= ': UTF-8 plain text';
$this->Mail->CharSet = 'UTF-8';
$this->Mail->Body = <<<'EOT'
Chinese text: 郵件內容為空
Russian text: Пустое тело сообщения
Armenian text: Հաղորդագրությունը դատարկ է
Czech text: Prázdné tělo zprávy
EOT;
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$msg = $this->Mail->getSentMIMEMessage();
self::assertStringNotContainsString("\r\n\r\nMIME-Version:", $msg, 'Incorrect MIME headers');
}
public function testMsgHTML()
{
$message = file_get_contents(realpath(\PHPMAILER_INCLUDE_DIR . '/examples/contentsutf8.html'));
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
$this->Mail->Body = '';
$this->Mail->AltBody = '';
$this->Mail->msgHTML($message, realpath(\PHPMAILER_INCLUDE_DIR . '/examples'));
$sub = $this->Mail->Subject . ': msgHTML';
$this->Mail->Subject .= $sub;
self::assertNotEmpty($this->Mail->Body, 'Body not set by msgHTML');
self::assertNotEmpty($this->Mail->AltBody, 'AltBody not set by msgHTML');
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->AltBody = '';
$this->Mail->msgHTML(
$message,
realpath(\PHPMAILER_INCLUDE_DIR . '/examples'),
static function ($html) {
return strtoupper(strip_tags($html));
}
);
$this->Mail->Subject = $sub . ' + custom html2text';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->msgHTML('<img src="/etc/hostname">test');
self::assertStringContainsString('src="/etc/hostname"', $this->Mail->Body);
$this->Mail->msgHTML('<img src="composer.json">test', realpath(\PHPMAILER_INCLUDE_DIR));
self::assertStringNotContainsString('src="composer.json"', $this->Mail->Body);
$this->Mail->msgHTML('<img src="../composer.json">test', realpath(\PHPMAILER_INCLUDE_DIR));
self::assertStringNotContainsString('src="composer.json"', $this->Mail->Body);
$this->Mail->msgHTML('<img src="cid:5d41402abc4b2a76b9719d911017c592">test');
self::assertStringContainsString('src="cid:5d41402abc4b2a76b9719d911017c592"', $this->Mail->Body);
$this->Mail->msgHTML('<img src="https://github.com/PHPMailer/PHPMailer/blob/master/composer.json">test');
self::assertStringContainsString(
'src="https://github.com/PHPMailer/PHPMailer/blob/master/composer.json"',
$this->Mail->Body
);
$this->Mail->msgHTML('<img src="//github.com/PHPMailer/PHPMailer/blob/master/composer.json">test');
self::assertStringContainsString(
'src= $this->Mail->Body
);
}
public function testHTMLAttachment()
{
$this->Mail->Body = 'This is the <strong>HTML</strong> part of the email.';
$this->Mail->Subject .= ': HTML + Attachment';
$this->Mail->isHTML(true);
$this->Mail->CharSet = 'UTF-8';
if (
!$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer_mini.png'),
'phpmailer_mini.png'
)
) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
self::assertFalse($this->Mail->addAttachment('phar://pharfile.php', 'pharfile.php'));
self::assertFalse($this->Mail->addAttachment('http://example.com/test.php', 'test.php'));
self::assertFalse(
$this->Mail->addAttachment(
'ssh2.sftp://user:pass@attacker-controlled.example.com:22/tmp/payload.phar',
'test.php'
)
);
self::assertFalse($this->Mail->addAttachment('x-1.cd+-://example.com/test.php', 'test.php'));
$filename = __FILE__ . md5(microtime()) . 'nonexistent_file.txt';
self::assertFalse($this->Mail->addAttachment($filename));
touch($filename);
chmod($filename, 0200);
self::assertFalse($this->Mail->addAttachment($filename));
chmod($filename, 0644);
unlink($filename);
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testAttachmentNaming()
{
$this->Mail->Body = 'Attachments.';
$this->Mail->Subject .= ': Attachments';
$this->Mail->isHTML(true);
$this->Mail->CharSet = 'UTF-8';
$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer_mini.png'),
'phpmailer_mini.png";.jpg'
);
$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer.png'),
'phpmailer.png'
);
$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/PHPMailer card logo.png'),
'PHPMailer card logo.png'
);
$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer_mini.png'),
'phpmailer_mini.png\\\";.jpg'
);
$this->buildBody();
$this->Mail->preSend();
$message = $this->Mail->getSentMIMEMessage();
self::assertStringContainsString(
'Content-Type: image/png; name="phpmailer_mini.png\";.jpg"',
$message,
'Name containing double quote should be escaped in Content-Type'
);
self::assertStringContainsString(
'Content-Disposition: attachment; filename="phpmailer_mini.png\";.jpg"',
$message,
'Filename containing double quote should be escaped in Content-Disposition'
);
self::assertStringContainsString(
'Content-Type: image/png; name=phpmailer.png',
$message,
'Name without special chars should not be quoted in Content-Type'
);
self::assertStringContainsString(
'Content-Disposition: attachment; filename=phpmailer.png',
$message,
'Filename without special chars should not be quoted in Content-Disposition'
);
self::assertStringContainsString(
'Content-Type: image/png; name="PHPMailer card logo.png"',
$message,
'Name with spaces should be quoted in Content-Type'
);
self::assertStringContainsString(
'Content-Disposition: attachment; filename="PHPMailer card logo.png"',
$message,
'Filename with spaces should be quoted in Content-Disposition'
);
}
public function testHTMLMultiAttachment()
{
$this->Mail->Body = 'This is the <strong>HTML</strong> part of the email.';
$this->Mail->Subject .= ': HTML + multiple Attachment';
$this->Mail->isHTML(true);
if (
!$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer_mini.png'),
'phpmailer_mini.png'
)
) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
if (
!$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer.png'),
'phpmailer.png'
)
) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testEmbeddedImage()
{
$this->Mail->msgHTML('<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>E-Mail Inline Image Test</title>
</head>
<body>
<p><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p>
</body>
</html>');
$this->Mail->preSend();
self::assertStringContainsString(
'Content-ID: <bb229a48bee31f5d54ca12dc9bd960c6@phpmailer.0>',
$this->Mail->getSentMIMEMessage(),
'Embedded image header encoding incorrect.'
);
}
public function testMultiEmbeddedImage()
{
$this->Mail->Body = 'Embedded Image: <img alt="phpmailer" src="' .
'cid:my-attach">' .
'Here is an image!</a>';
$this->Mail->Subject .= ': Embedded Image + Attachment';
$this->Mail->isHTML(true);
if (
!$this->Mail->addEmbeddedImage(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer.png'),
'my-attach',
'phpmailer.png',
'base64',
'image/png'
)
) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
if (!$this->Mail->addAttachment(__FILE__, 'test.txt')) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testAltBody()
{
$this->Mail->Body = 'This is the <strong>HTML</strong> part of the email.';
$this->Mail->AltBody = 'Here is the plain text body of this message. ' .
'It should be quite a few lines. It should be wrapped at ' .
'40 characters. Make sure that it is.';
$this->Mail->WordWrap = 40;
$this->addNote('This is a multipart/alternative email');
$this->Mail->Subject .= ': AltBody + Word Wrap';
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testAltBodyAttachment()
{
$this->Mail->Body = 'This is the <strong>HTML</strong> part of the email.';
$this->Mail->AltBody = 'This is the text part of the email.';
$this->Mail->Subject .= ': AltBody + Attachment';
$this->Mail->isHTML(true);
if (!$this->Mail->addAttachment(__FILE__, 'test_attach.txt')) {
self::assertTrue(false, $this->Mail->ErrorInfo);
return;
}
self::assertFalse($this->Mail->addAttachment('\\\\nowhere\\nothing'));
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testMultipleSend()
{
$this->Mail->Body = 'Sending two messages without keepalive';
$this->buildBody();
$subject = $this->Mail->Subject;
$this->Mail->Subject = $subject . ': SMTP 1';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->Subject = $subject . ': SMTP 2';
$this->Mail->Sender = 'blah@example.com';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testEmptyBody()
{
$this->buildBody();
$this->Mail->Body = '';
$this->Mail->Subject = $this->Mail->Subject . ': Empty Body';
$this->Mail->isMail();
$this->Mail->AllowEmpty = true;
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->AllowEmpty = false;
self::assertFalse($this->Mail->send(), $this->Mail->ErrorInfo);
}
public function testSmtpKeepAlive()
{
$this->Mail->Body = 'SMTP keep-alive test.';
$this->buildBody();
$subject = $this->Mail->Subject;
$this->Mail->SMTPKeepAlive = true;
$this->Mail->Subject = $subject . ': SMTP keep-alive 1';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->Subject = $subject . ': SMTP keep-alive 2';
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->smtpClose();
}
public function testAddressing()
{
self::assertFalse($this->Mail->addAddress(''), 'Empty address accepted');
self::assertFalse($this->Mail->addAddress('', 'Nobody'), 'Empty address with name accepted');
self::assertFalse($this->Mail->addAddress('a@example..com'), 'Invalid address accepted');
self::assertTrue($this->Mail->addAddress('a@example.com'), 'Addressing failed');
self::assertFalse($this->Mail->addAddress('a@example.com'), 'Duplicate addressing failed');
self::assertTrue($this->Mail->addCC('b@example.com'), 'CC addressing failed');
self::assertFalse($this->Mail->addCC('b@example.com'), 'CC duplicate addressing failed');
self::assertFalse($this->Mail->addCC('a@example.com'), 'CC duplicate addressing failed (2)');
self::assertTrue($this->Mail->addBCC('c@example.com'), 'BCC addressing failed');
self::assertFalse($this->Mail->addBCC('c@example.com'), 'BCC duplicate addressing failed');
self::assertFalse($this->Mail->addBCC('a@example.com'), 'BCC duplicate addressing failed (2)');
$this->Mail->clearCCs();
$this->Mail->clearBCCs();
}
public function testAddressEscaping()
{
$this->Mail->Subject .= ': Address escaping';
$this->Mail->clearAddresses();
$this->Mail->addAddress('foo@example.com', 'Tim "The Book" O\'Reilly');
$this->Mail->Body = 'Test correct escaping of quotes in addresses.';
$this->buildBody();
$this->Mail->preSend();
$b = $this->Mail->getSentMIMEMessage();
self::assertStringContainsString('To: "Tim \"The Book\" O\'Reilly" <foo@example.com>', $b);
$this->Mail->Subject .= ': Address escaping invalid';
$this->Mail->clearAddresses();
$this->Mail->addAddress('foo@example.com', 'Tim "The Book" O\'Reilly');
$this->Mail->addAddress('invalidaddressexample.com', 'invalidaddress');
$this->Mail->Body = 'invalid address';
$this->buildBody();
$this->Mail->preSend();
self::assertSame('Invalid address: (to): invalidaddressexample.com', $this->Mail->ErrorInfo);
$this->Mail->addAttachment(
realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer_mini.png'),
'phpmailer_mini.png'
);
self::assertTrue($this->Mail->attachmentExists());
}
public function testMIMEStructure()
{
$this->Mail->Subject .= ': MIME structure';
$this->Mail->Body = '<h3>MIME structure test.</h3>';
$this->Mail->AltBody = 'MIME structure test.';
$this->buildBody();
$this->Mail->preSend();
self::assertMatchesRegularExpression(
"/Content-Transfer-Encoding: 8bit\r\n\r\n" .
'This is a multi-part message in MIME format./',
$this->Mail->getSentMIMEMessage(),
'MIME structure broken'
);
}
public function testBCCAddressing()
{
$this->Mail->isSMTP();
$this->Mail->Subject .= ': BCC-only addressing';
$this->buildBody();
$this->Mail->clearAllRecipients();
self::assertTrue($this->Mail->addBCC('a@example.com'), 'BCC addressing failed');
$this->Mail->preSend();
$b = $this->Mail->getSentMIMEMessage();
self::assertStringNotContainsString('a@example.com', $b);
self::assertTrue($this->Mail->send(), 'send failed');
}
public function testAddAttachmentEncodingException()
{
$this->expectException(Exception::class);
$mail = new PHPMailer(true);
$mail->addAttachment(__FILE__, 'test.txt', 'invalidencoding');
}
public function testDeletedAttachmentException()
{
$this->expectException(Exception::class);
$filename = __FILE__ . md5(microtime()) . 'test.txt';
touch($filename);
$this->Mail = new PHPMailer(true);
$this->Mail->addAttachment($filename);
unlink($filename);
$this->Mail->send();
}
public function testDeletedAttachmentError()
{
$filename = __FILE__ . md5(microtime()) . 'test.txt';
touch($filename);
$this->Mail = new PHPMailer();
$this->Mail->addAttachment($filename);
unlink($filename);
self::assertFalse($this->Mail->send());
}
public function testBase64()
{
$this->Mail->Subject .= ': Base-64 encoding';
$this->Mail->Encoding = 'base64';
$this->buildBody();
self::assertTrue($this->Mail->send(), 'Base64 encoding failed');
}
public function testSigning()
{
$this->Mail->Subject .= ': S/MIME signing';
$this->Mail->Body = 'This message is S/MIME signed.';
$this->buildBody();
$dn = [
'countryName' => 'UK',
'stateOrProvinceName' => 'Here',
'localityName' => 'There',
'organizationName' => 'PHP',
'organizationalUnitName' => 'PHPMailer',
'commonName' => 'PHPMailer Test',
'emailAddress' => 'phpmailer@example.com',
];
$keyconfig = [
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$password = 'password';
$certfile = 'certfile.pem';
$keyfile = 'keyfile.pem';
$pk = openssl_pkey_new($keyconfig);
$csr = openssl_csr_new($dn, $pk);
$cert = openssl_csr_sign($csr, null, $pk, 1);
openssl_x509_export($cert, $certout);
file_put_contents($certfile, $certout);
openssl_pkey_export($pk, $pkeyout, $password);
file_put_contents($keyfile, $pkeyout);
$this->Mail->sign(
$certfile,
$keyfile,
$password
);
self::assertTrue($this->Mail->send(), 'S/MIME signing failed');
$msg = $this->Mail->getSentMIMEMessage();
self::assertStringNotContainsString("\r\n\r\nMIME-Version:", $msg, 'Incorrect MIME headers');
unlink($certfile);
unlink($keyfile);
}
public function testSigningWithCA()
{
$this->Mail->Subject .= ': S/MIME signing with CA';
$this->Mail->Body = 'This message is S/MIME signed with an extra CA cert.';
$this->buildBody();
$certprops = [
'countryName' => 'UK',
'stateOrProvinceName' => 'Here',
'localityName' => 'There',
'organizationName' => 'PHP',
'organizationalUnitName' => 'PHPMailer',
'commonName' => 'PHPMailer Test',
'emailAddress' => 'phpmailer@example.com',
];
$cacertprops = [
'countryName' => 'UK',
'stateOrProvinceName' => 'Here',
'localityName' => 'There',
'organizationName' => 'PHP',
'organizationalUnitName' => 'PHPMailer CA',
'commonName' => 'PHPMailer Test CA',
'emailAddress' => 'phpmailer@example.com',
];
$keyconfig = [
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$password = 'password';
$cacertfile = 'cacertfile.pem';
$cakeyfile = 'cakeyfile.pem';
$certfile = 'certfile.pem';
$keyfile = 'keyfile.pem';
$capk = openssl_pkey_new($keyconfig);
$csr = openssl_csr_new($cacertprops, $capk);
$cert = openssl_csr_sign($csr, null, $capk, 1);
openssl_x509_export($cert, $certout);
file_put_contents($cacertfile, $certout);
openssl_pkey_export($capk, $pkeyout, $password);
file_put_contents($cakeyfile, $pkeyout);
$pk = openssl_pkey_new($keyconfig);
$csr = openssl_csr_new($certprops, $pk);
$cacert = file_get_contents($cacertfile);
$cert = openssl_csr_sign($csr, $cacert, $capk, 1);
openssl_x509_export($cert, $certout);
file_put_contents($certfile, $certout);
openssl_pkey_export($pk, $pkeyout, $password);
file_put_contents($keyfile, $pkeyout);
$this->Mail->sign(
$certfile,
$keyfile,
$password,
$cacertfile
);
self::assertTrue($this->Mail->send(), 'S/MIME signing with CA failed');
unlink($cacertfile);
unlink($cakeyfile);
unlink($certfile);
unlink($keyfile);
}
public function testLineBreaks()
{
$this->Mail->isSMTP();
$this->Mail->preSend();
$this->Mail->Subject = 'PHPMailer DOS line breaks';
$this->Mail->Body = "This message\r\ncontains\r\nDOS-format\r\nCRLF line breaks.";
self::assertTrue($this->Mail->send());
$this->Mail->Subject = 'PHPMailer UNIX line breaks';
$this->Mail->Body = "This message\ncontains\nUNIX-format\nLF line breaks.";
self::assertTrue($this->Mail->send());
$this->Mail->Encoding = 'quoted-printable';
$this->Mail->Subject = 'PHPMailer DOS line breaks, QP';
$this->Mail->Body = "This message\r\ncontains\r\nDOS-format\r\nCRLF line breaks.";
self::assertTrue($this->Mail->send());
$this->Mail->Subject = 'PHPMailer UNIX line breaks, QP';
$this->Mail->Body = "This message\ncontains\nUNIX-format\nLF line breaks.";
self::assertTrue($this->Mail->send());
}
public function testMiscellaneous()
{
$this->Mail->clearAttachments();
$this->Mail->isHTML(false);
$this->Mail->isSMTP();
$this->Mail->isMail();
$this->Mail->isSendmail();
$this->Mail->isQmail();
$this->Mail->Sender = '';
$this->Mail->createHeader();
}
public function testBadSMTP()
{
$this->Mail->smtpConnect();
$smtp = $this->Mail->getSMTPInstance();
self::assertFalse($smtp->mail("somewhere\nbad"), 'Bad SMTP command containing breaks accepted');
}
public function testConfirmReadingTo()
{
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
$this->buildBody();
$this->Mail->ConfirmReadingTo = 'test@example..com'; self::assertFalse($this->Mail->send(), $this->Mail->ErrorInfo);
$this->Mail->ConfirmReadingTo = ' test@example.com'; self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
self::assertSame(
'test@example.com',
$this->Mail->ConfirmReadingTo,
'Unexpected read receipt address'
);
$letter = html_entity_decode('ç', ENT_COMPAT, PHPMailer::CHARSET_UTF8);
$this->Mail->ConfirmReadingTo = 'test@fran' . $letter . 'ois.ch'; if (PHPMailer::idnSupported()) {
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
self::assertSame(
'test@xn--franois-xxa.ch',
$this->Mail->ConfirmReadingTo,
'IDN address not converted to punycode'
);
} else {
self::assertFalse($this->Mail->send(), $this->Mail->ErrorInfo);
}
}
public function testConvertEncoding()
{
if (!PHPMailer::idnSupported()) {
self::markTestSkipped('intl and/or mbstring extensions are not available');
}
$this->Mail->clearAllRecipients();
$letter = html_entity_decode('ç', ENT_COMPAT, PHPMailer::CHARSET_ISO88591);
$domain = '@' . 'fran' . $letter . 'ois.ch';
$this->Mail->addAddress('test' . $domain);
$this->Mail->addCC('test+cc' . $domain);
$this->Mail->addBCC('test+bcc' . $domain);
self::assertEmpty($this->Mail->getToAddresses(), 'Bad "to" recipients');
self::assertEmpty($this->Mail->getCcAddresses(), 'Bad "cc" recipients');
self::assertEmpty($this->Mail->getBccAddresses(), 'Bad "bcc" recipients');
$this->Mail->clearBCCs();
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
$domain = $this->Mail->punyencodeAddress($domain);
self::assertSame(
[['test' . $domain, '']],
$this->Mail->getToAddresses(),
'Bad "to" recipients'
);
self::assertSame(
[['test+cc' . $domain, '']],
$this->Mail->getCcAddresses(),
'Bad "cc" recipients'
);
self::assertEmpty($this->Mail->getBccAddresses(), 'Bad "bcc" recipients');
}
public function testDuplicateIDNRemoved()
{
if (!PHPMailer::idnSupported()) {
self::markTestSkipped('intl and/or mbstring extensions are not available');
}
$this->Mail->clearAllRecipients();
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
self::assertTrue($this->Mail->addAddress('test@françois.ch'));
self::assertFalse($this->Mail->addAddress('test@françois.ch'));
self::assertTrue($this->Mail->addAddress('test@FRANÇOIS.CH'));
self::assertFalse($this->Mail->addAddress('test@FRANÇOIS.CH'));
self::assertTrue($this->Mail->addAddress('test@xn--franois-xxa.ch'));
self::assertFalse($this->Mail->addAddress('test@xn--franois-xxa.ch'));
self::assertFalse($this->Mail->addAddress('test@XN--FRANOIS-XXA.CH'));
$this->buildBody();
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
self::assertCount(
1,
$this->Mail->getToAddresses(),
'Bad count of "to" recipients'
);
}
public function testSmtpConnect()
{
$this->Mail->SMTPDebug = SMTP::DEBUG_LOWLEVEL; self::assertTrue($this->Mail->smtpConnect(), 'SMTP single connect failed');
$this->Mail->smtpClose();
$this->Mail->Host = ' localhost:12345 ; ' . $_REQUEST['mail_host'] . ' ';
self::assertTrue($this->Mail->smtpConnect(), 'SMTP hosts with stray spaces failed');
$this->Mail->smtpClose();
$this->Mail->Host = $_REQUEST['mail_host'];
self::assertTrue($this->Mail->smtpConnect(['ssl' => ['verify_depth' => 10]]));
$this->Smtp = $this->Mail->getSMTPInstance();
self::assertInstanceOf(\get_class($this->Smtp), $this->Mail->setSMTPInstance($this->Smtp));
$this->Mail->smtpClose();
}
public function testGivenIdnAddress_addAddress_returns_true()
{
if (file_exists(\PHPMAILER_INCLUDE_DIR . '/test/fakefunctions.php') === false) {
$this->markTestSkipped('/test/fakefunctions.php file not found');
}
include \PHPMAILER_INCLUDE_DIR . '/test/fakefunctions.php';
$this->assertTrue($this->Mail->addAddress('test@françois.ch'));
}
public function testErroneousAddress_addAddress_returns_false()
{
$this->assertFalse($this->Mail->addAddress('mehome.com'));
}
}