MailHelper.php
4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Mail;
defined('JPATH_PLATFORM') or die;
/**
* Email helper class, provides static methods to perform various tasks relevant
* to the Joomla email routines.
*
* TODO: Test these methods as the regex work is first run and not tested thoroughly
*
* @since 1.7.0
*/
abstract class MailHelper
{
/**
* Cleans single line inputs.
*
* @param string $value String to be cleaned.
*
* @return string Cleaned string.
*
* @since 1.7.0
*/
public static function cleanLine($value)
{
$value = \JStringPunycode::emailToPunycode($value);
return trim(preg_replace('/(%0A|%0D|\n+|\r+)/i', '', $value));
}
/**
* Cleans multi-line inputs.
*
* @param string $value Multi-line string to be cleaned.
*
* @return string Cleaned multi-line string.
*
* @since 1.7.0
*/
public static function cleanText($value)
{
return trim(preg_replace('/(%0A|%0D|\n+|\r+)(content-type:|to:|cc:|bcc:)/i', '', $value));
}
/**
* Cleans any injected headers from the email body.
*
* @param string $body email body string.
*
* @return string Cleaned email body string.
*
* @since 1.7.0
*/
public static function cleanBody($body)
{
// Strip all email headers from a string
return preg_replace("/((From:|To:|Cc:|Bcc:|Subject:|Content-type:) ([\S]+))/", '', $body);
}
/**
* Cleans any injected headers from the subject string.
*
* @param string $subject email subject string.
*
* @return string Cleaned email subject string.
*
* @since 1.7.0
*/
public static function cleanSubject($subject)
{
return preg_replace("/((From:|To:|Cc:|Bcc:|Content-type:) ([\S]+))/", '', $subject);
}
/**
* Verifies that an email address does not have any extra headers injected into it.
*
* @param string $address email address.
*
* @return mixed email address string or boolean false if injected headers are present.
*
* @since 1.7.0
*/
public static function cleanAddress($address)
{
if (preg_match("[\s;,]", $address))
{
return false;
}
return $address;
}
/**
* Verifies that the string is in a proper email address format.
*
* @param string $email String to be verified.
*
* @return boolean True if string has the correct format; false otherwise.
*
* @since 1.7.0
*/
public static function isEmailAddress($email)
{
// Split the email into a local and domain
$atIndex = strrpos($email, '@');
$domain = substr($email, $atIndex + 1);
$local = substr($email, 0, $atIndex);
// Check Length of domain
$domainLen = strlen($domain);
if ($domainLen < 1 || $domainLen > 255)
{
return false;
}
/*
* Check the local address
* We're a bit more conservative about what constitutes a "legal" address, that is, a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-
* The first and last character in local cannot be a period ('.')
* Also, period should not appear 2 or more times consecutively
*/
$allowed = "a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-";
$regex = "/^[$allowed][\.$allowed]{0,63}$/";
if (!preg_match($regex, $local) || substr($local, -1) == '.' || $local[0] == '.' || preg_match('/\.\./', $local))
{
return false;
}
// No problem if the domain looks like an IP address, ish
$regex = '/^[0-9\.]+$/';
if (preg_match($regex, $domain))
{
return true;
}
// Check Lengths
$localLen = strlen($local);
if ($localLen < 1 || $localLen > 64)
{
return false;
}
// Check the domain
$domain_array = explode('.', $domain);
$regex = '/^[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/';
foreach ($domain_array as $domain)
{
// Convert domain to punycode
$domain = \JStringPunycode::toPunycode($domain);
// Must be something
if (!$domain)
{
return false;
}
// Check for invalid characters
if (!preg_match($regex, $domain))
{
return false;
}
// Check for a dash at the beginning of the domain
if (strpos($domain, '-') === 0)
{
return false;
}
// Check for a dash at the end of the domain
$length = strlen($domain) - 1;
if (strpos($domain, '-', $length) === $length)
{
return false;
}
}
return true;
}
}