source: trunk/lib/Email.inc.php @ 23

Last change on this file since 23 was 23, checked in by scdev, 18 years ago

Added Email() class to work with verification, and sending of emails and templates. Updated Formvalidator to use the regex in Email().

File size: 10.5 KB
Line 
1<?php
2/**
3 * Email.inc.php
4 * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
5 *
6 * Easy email template usage.
7 *
8 * @author  Quinn Comendant <quinn@strangecode.com>
9 * @version 1.0
10 
11-------------------------------------------------------------------------------------
12// Example.
13$email = new Email(array(
14    'to' => array($frm['email'], 'q@lovemachine.local'),
15    'from' => sprintf('%s <%s>', App::getParam('site_name'), App::getParam('site_email')),
16    'subject' => 'Your Golbon account has been activated',
17));
18$email->setTemplate('email_registration_confirm.ihtml');
19$email->replace(array(
20    'site_name' => App::getParam('site_name'),
21    'site_url' => App::getParam('site_url'),
22    'username' => $frm['username'],
23    'password' => $frm['password1'],
24    'inviting_member_business_name' => $frm['inviting_member_business_name'],
25));
26if ($email->send()) {
27    App::raiseMsg(sprintf(_("A confirmation email has been sent to %s."), $frm['email']), MSG_SUCCESS, __FILE__, __LINE__);
28} else {
29    App::logMsg(sprintf('Error sending confirmation email to address %s', $frm['email']), LOG_DEBUG, __FILE__, __LINE__);
30    App::raiseMsg(sprintf('We tried sending you a confirmation email to address %s but there was an error. After logging in, please visit the "My Account" page to confirm that this address is correct.', $frm['email']), MSG_NOTICE, __FILE__, __LINE__);
31}
32-------------------------------------------------------------------------------------
33 */
34class Email {
35
36    var $_params = array(
37        'to' => null,
38        'from' => null,
39        'subject' => null,
40        'regex' => null
41    );
42    var $_template;
43    var $_template_replaced;
44    var $regex;
45
46    /**
47     * Constructor.
48     *
49     * @access  public
50     * @param   array   $params     Array of object parameters.
51     * @author  Quinn Comendant <quinn@strangecode.com>
52     * @since   28 Nov 2005 12:59:41
53     */
54    function Email($params=null)
55    {
56        $this->setParam(array('regex' => '/^(?:[^,@]*\s+|[^,@]*(<)|)'   // Display name
57        . '((?:[^.<>\s@\",\[\]]+[^<>\s@\",\[\]])*[^.<>\s@\",\[\]]+)'    // Local-part
58        . '@'                                                           // @
59        . '((?:(\[)|[A-Z0-9]?)'                                         // Domain, first char
60        . '(?(4)'                                                       // Domain conditional for if first domain char is [
61        . '(?:[0-9]{1,3}\.){3}[0-9]{1,3}\]'                             // TRUE, matches IP address
62        . '|'
63        . '[.-]?(?:[A-Z0-9]+[-.])*(?:[A-Z0-9]+\.)+[A-Z]{2,6}))'         // FALSE, matches domain name
64        . '(?(1)'                                                       // Comment conditional for if initial < exists
65        . '(?:>\s*|>\s+\([^,@]+\)\s*)'                                  // TRUE, ensure ending >
66        . '|'
67        . '(?:|\s*|\s+\([^,@]+\)\s*))$/i'));                            // FALSE ensure there is no ending >
68
69        $this->setParam($params);
70    }
71
72    /**
73     * Set (or overwrite existing) parameters by passing an array of new parameters.
74     *
75     * @access public
76     * @param  array    $params     Array of parameters (key => val pairs).
77     */
78    function setParam($params)
79    {
80        if (isset($params) && is_array($params)) {
81
82            // Enforce valid email addresses.
83            if (isset($params['to']) && !$this->validEmail($params['to'])) {
84                $params['to'] = null;
85            }
86            if (isset($params['from']) && !$this->validEmail($params['from'])) {
87                $params['from'] = null;
88            }
89
90            // Merge new parameters with old overriding only those passed.
91            $this->_params = array_merge($this->_params, $params);
92        } else {
93            App::logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
94        }
95    }
96
97    /**
98     * Return the value of a parameter, if it exists.
99     *
100     * @access public
101     * @param string $param        Which parameter to return.
102     * @return mixed               Configured parameter value.
103     */
104    function getParam($param)
105    {
106        if (isset($this->_params[$param])) {
107            return $this->_params[$param];
108        } else {
109            App::logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
110            return null;
111        }
112    }
113
114    /**
115     * Loads template from file to generate email body.
116     *
117     * @access  public
118     * @param   string  $template   Filename of email template.
119     * @author  Quinn Comendant <quinn@strangecode.com>
120     * @since   28 Nov 2005 12:56:23
121     */
122    function setTemplate($template)
123    {
124        // Load file, using include_path.
125        if (!$this->_template = file_get_contents($template, true)) {
126            App::logMsg(sprintf('Email template file does not exist: %s', $template), LOG_ERR, __FILE__, __LINE__);
127            $this->_template = null;
128            $this->_template_replaced = null;
129            return false;
130        }
131        $this->_template_replaced = null;
132        return true;
133    }
134
135    /**
136     * Loads template from string to generate email body.
137     *
138     * @access  public
139     * @param   string  $template   Filename of email template.
140     * @author  Quinn Comendant <quinn@strangecode.com>
141     * @since   28 Nov 2005 12:56:23
142     */
143    function setString($string)
144    {
145        // Load file, using include_path.
146        if ('' == $string) {
147            App::logMsg(sprintf('Empty string provided.', null), LOG_ERR, __FILE__, __LINE__);
148            $this->_template_replaced = null;
149            return false;
150        } else {
151            $_template = $string;
152            $this->_template_replaced = null;
153            return true;
154        }
155    }
156   
157    /**
158     * Replace variables in template with argument data.
159     *
160     * @access  public
161     * @param   array   $replacements   Array keys are the values to search for, array vales are the replacement values.
162     * @author  Quinn Comendant <quinn@strangecode.com>
163     * @since   28 Nov 2005 13:08:51
164     */
165    function replace($replacements)
166    {
167        if (!isset($this->_template)) {
168            App::logMsg(sprintf('Cannot replace variables, no template defined.', null), LOG_ERR, __FILE__, __LINE__);
169            return false;
170        }
171
172        if (!is_array($replacements)) {
173            App::logMsg(sprintf('Cannot replace variables, invalid replacements.', null), LOG_ERR, __FILE__, __LINE__);
174            return false;
175        }
176       
177        // Apply regex pattern to search elements.
178        $search = array_keys($replacements);
179        array_walk($search, create_function('&$v', '$v = "/{" . preg_quote($v) . "}/i";'));
180
181        // Replace values.
182        $replace = array_values($replacements);
183
184        $this->_template_replaced = preg_replace($search, $replace, $this->_template);
185    }
186
187    /**
188     * Send email using PHP's mail() function.
189     *
190     * @access  public
191     * @param   string  $to
192     * @param   string  $from
193     * @param   string  $subject
194     * @author  Quinn Comendant <quinn@strangecode.com>
195     * @since   28 Nov 2005 12:56:09
196     */
197    function send($to=null, $from=null, $subject=null)
198    {
199        if (isset($to)) {
200             $this->setParam(array('to' => $to));
201        }
202        if (isset($from)) {
203             $this->setParam(array('from' => $from));
204        }
205        if (isset($subject)) {
206             $this->setParam(array('subject' => $subject));
207        }
208
209        if (!isset($this->_template)) {
210            App::logMsg(sprintf('Cannot send email. Template not set.', null), LOG_ERR, __FILE__, __LINE__);
211            return false;
212        } else if (!isset($this->_params['to'])) {
213            App::logMsg(sprintf('Cannot send email. TO not defined.', null), LOG_ERR, __FILE__, __LINE__);
214            return false;
215        } else if (!isset($this->_params['from'])) {
216            App::logMsg(sprintf('Cannot send email. FROM not defined.', null), LOG_ERR, __FILE__, __LINE__);
217            return false;
218        } else if (!isset($this->_params['subject'])) {
219            App::logMsg(sprintf('Cannot send email. SUBJECT not defined.', null), LOG_ERR, __FILE__, __LINE__);
220            return false;
221        }
222
223        $final_body = wordwrap(isset($this->_template_replaced) ? $this->_template_replaced : $this->_template);
224        // Test that all placeholders have been replaced.
225        if (preg_match('/({[^}]+})/', $final_body, $unreplaced_match)) {
226            App::logMsg(sprintf('Cannot send email. Variables left unreplaced in template: %s', (isset($unreplaced_match) ? $unreplaced_match[1] : '')), LOG_ERR, __FILE__, __LINE__);
227            return false;
228        }
229       
230        $final_to = is_array($this->_params['to']) ? join(', ', $this->_params['to']) : $this->_params['to'];
231        $final_from = sprintf("From: %s\r\n", $this->_params['from']);
232        $envelope_sender_header = sprintf('-f %s', preg_replace('/^.*<?([^\s@\[\]<>()]+\@[A-Za-z0-9.-]{1,}\.[A-Za-z]{2,5})>?$/iU', '$1', $this->_params['from']));
233        if (!mail($final_to, $this->_params['subject'], $final_body, $final_from, $envelope_sender_header)) {
234            App::logMsg(sprintf('Email failure with parameters: %s, %s, %s, %s', $this->_params['to'], $this->_params['subject'], str_replace("\r\n", '', $final_from), $envelope_sender_header), LOG_NOTICE, __FILE__, __LINE__);
235            return false;
236        }
237       
238        return true;
239    }
240   
241    /**
242     * Validates an email address based on the recommendations in RFC 3696.
243     * Is more loose than restrictive, to allow the many valid variants of
244     * email addresses while catching the most common mistakes. Checks an array too.
245     * http://www.faqs.org/rfcs/rfc822.html
246     * http://www.faqs.org/rfcs/rfc2822.html
247     * http://www.faqs.org/rfcs/rfc3696.html
248     * http://www.faqs.org/rfcs/rfc1035.html
249     *
250     * @access  public
251     * @param   mixed  $email  Address to check, string or array.
252     * @return  bool    Validity of address.
253     * @author  Quinn Comendant <quinn@strangecode.com>
254     * @since   30 Nov 2005 22:00:50
255     */
256    function validEmail($email)
257    {
258        if (is_array($email)) {
259            foreach ($email as $e) {
260                if (!$this->validEmail($e)) {
261                    return false;
262                }
263            }
264            return true;
265        } else {
266            if (!preg_match($this->getParam('regex'), $email)) {
267                App::logMsg(sprintf('Invalid email: %s', $email), LOG_DEBUG, __FILE__, __LINE__);
268                return false;
269            }
270            return true;
271        }
272    }
273}
274
275?>
Note: See TracBrowser for help on using the repository browser.