1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace org\example\Contact; |
4
|
|
|
|
5
|
|
|
use PHPMailer; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Application logic for contact form |
9
|
|
|
*/ |
10
|
|
|
class ContactModel |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* @var array Holds all titles (salutations) that may be chosen from |
14
|
|
|
*/ |
15
|
|
|
protected $titles = array( |
16
|
|
|
#0 => intentionally left blank ("not chosen") |
|
|
|
|
17
|
|
|
1 => 'Mr', |
18
|
|
|
2 => 'Ms', |
19
|
|
|
3 => 'Company' |
20
|
|
|
); |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var string Path to PHPMailer directory in local file system |
24
|
|
|
*/ |
25
|
|
|
protected $pathToMailer = './library/phpmailer/PHPMailer_v5.1'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var string All e-mails will be sent to this address |
29
|
|
|
*/ |
30
|
|
|
protected $emailRecipient = '[email protected]'; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var int Number of seconds a session has to wait before a second e-mail |
34
|
|
|
* will be accepted (protection from spam and accidental double |
35
|
|
|
* posts) |
36
|
|
|
* @todo Probably not the most clever way to do this |
37
|
|
|
*/ |
38
|
|
|
protected $emailInterval = 60; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Returns all titles (salutations) a user may chose from |
42
|
|
|
* |
43
|
|
|
* @return array Titles to chose from |
44
|
|
|
*/ |
45
|
|
|
public function getTitles() |
46
|
|
|
{ |
47
|
|
|
return $this->titles; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Sanitizes and validates input, calls the method to mail the supplied |
52
|
|
|
* contact form data and returns an array of errors |
53
|
|
|
* |
54
|
|
|
* @return array Errors (an empty array indicates there are no errors) |
55
|
|
|
*/ |
56
|
|
|
public function sendEmailFromPOST() |
|
|
|
|
57
|
|
|
{ |
58
|
|
|
$errors = array(); |
59
|
|
|
|
60
|
|
|
// Do not overwrite original data in $_POST |
61
|
|
|
$data = $_POST; |
62
|
|
|
|
63
|
|
|
// Make sure every field is set |
64
|
|
|
$data['email'] = (isset($data['email'])) |
65
|
|
|
? trim((string) $data['email']) : ''; |
66
|
|
|
$data['title'] = (isset($data['title'])) |
67
|
|
|
? (int) $data['title'] : 0; |
68
|
|
|
$data['name'] = (isset($data['name'])) |
69
|
|
|
? trim((string) $data['name']) : ''; |
70
|
|
|
$data['phone'] = (isset($data['phone'])) |
71
|
|
|
? trim((string) $data['phone']) : ''; |
72
|
|
|
$data['callback'] = (isset($data['callback'])) |
73
|
|
|
? (bool) $data['callback'] : false; |
74
|
|
|
|
75
|
|
|
// Validate input |
76
|
|
|
$data['email'] = preg_match('/^[^@\s]+@[^@\s]+\.[^@\s.]+$/', |
77
|
|
|
$data['email']) |
78
|
|
|
? $data['email'] : ''; |
79
|
|
|
$data['title'] = (isset($this->titles[$data['title']])) |
80
|
|
|
? $data['title'] : 0; |
81
|
|
|
|
82
|
|
|
// Generate error messages for fields that have to be filled |
83
|
|
|
if ($data['email'] === '') { |
84
|
|
|
$errors[] = 'Please provide a valid e-mail address.'; |
85
|
|
|
} |
86
|
|
|
if ($data['title'] === 0) { |
87
|
|
|
$errors[] = 'Please choose a title from the list.'; |
88
|
|
|
} |
89
|
|
|
if ($data['name'] === '') { |
90
|
|
|
$errors[] = 'Please enter your name.'; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
// In case of error, return |
94
|
|
|
if (!empty($errors)) { |
95
|
|
|
return $errors; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
// Otherwise, we're clear to mail the data |
99
|
|
|
$errors = $this->doSendEmail($data); |
100
|
|
|
|
101
|
|
|
return $errors; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Mails data from contact form |
106
|
|
|
* |
107
|
|
|
* @param array $data Sanitized and validated form input |
108
|
|
|
* @return array Errors (an empty array indicates there are no errors) |
109
|
|
|
*/ |
110
|
|
|
protected function doSendEmail($data) |
|
|
|
|
111
|
|
|
{ |
112
|
|
|
// Application relies on session for spam protection |
113
|
|
|
if (!isset($_SESSION['contact']['lastEmailSent'])) { |
114
|
|
|
return array('You have to accept the session cookie.'); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
// See if enough time has passed to send another e-mail |
118
|
|
|
if (isset($_SESSION['contact']['lastEmailSent']) |
119
|
|
|
&& ($_SESSION['contact']['lastEmailSent'] |
120
|
|
|
+ $this->emailInterval > time()) |
121
|
|
|
) { |
122
|
|
|
return array(sprintf( |
123
|
|
|
'You have to wait a total of %d seconds before you can ' |
124
|
|
|
. 'send another e-mail.', $this->emailInterval)); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
require_once $this->pathToMailer . '/class.phpmailer.php'; |
128
|
|
|
|
129
|
|
|
// Generate body |
130
|
|
|
$body = sprintf("E-Mail: %s\n", $data['email']) |
131
|
|
|
. sprintf("Title: %s\n", $this->titles[$data['title']]) |
132
|
|
|
. sprintf("Name: %s\n", $data['name']) |
133
|
|
|
. sprintf("Phone: %s\n", $data['phone']) |
134
|
|
|
. sprintf("Callback: %s", ($data['callback']) ? 'yes' : 'no'); |
135
|
|
|
|
136
|
|
|
$mail = new PHPMailer(); |
137
|
|
|
|
138
|
|
|
// Setup mailing method |
139
|
|
|
/** @todo Configuration settings should be moved to a config file */ |
140
|
|
|
$mail->IsSMTP(true); |
141
|
|
|
$mail->Host = 'ssl://smtp.example.org:465'; |
142
|
|
|
$mail->SMTPAuth = true; |
143
|
|
|
$mail->Username = ''; |
144
|
|
|
$mail->Password = ''; |
145
|
|
|
|
146
|
|
|
// Set e-mail headers to more or less fitting values |
147
|
|
|
$mail->Subject = 'example.org -- Contact inquiry'; |
148
|
|
|
$mail->Body = $body; |
149
|
|
|
$mail->CharSet = 'UTF-8'; |
150
|
|
|
|
151
|
|
|
$mail->AddReplyTo($data['email'], $data['name']); |
152
|
|
|
$mail->SetFrom('[email protected]'); |
153
|
|
|
|
154
|
|
|
$mail->AddAddress($this->emailRecipient); |
155
|
|
|
|
156
|
|
|
// Try to send mail, return errors on failure |
157
|
|
|
if (!$mail->Send()) { |
158
|
|
|
return array('Mailer Error: ' . $mail->ErrorInfo); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
// E-mail sent, as far as we can tell. No errors |
162
|
|
|
$_SESSION['contact']['lastEmailSent'] = time(); |
163
|
|
|
$_POST = array(); |
164
|
|
|
|
165
|
|
|
return array(); |
166
|
|
|
} |
167
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.