├── .gitignore ├── example ├── images │ └── mail │ │ └── yii.png ├── files │ └── yii-1.1.0-validator-cheatsheet.pdf └── protected │ ├── views │ ├── mail │ │ ├── contact.php │ │ └── cron.php │ ├── layouts │ │ └── mail.php │ └── site │ │ └── contact.php │ ├── config │ ├── console.php │ ├── mail.php │ └── main.php │ ├── yiic.php │ ├── commands │ └── CronCommand.php │ └── controllers │ └── SiteController.php ├── composer.json ├── README.md └── src └── YiiMailer.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor -------------------------------------------------------------------------------- /example/images/mail/yii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vernes/YiiMailer/HEAD/example/images/mail/yii.png -------------------------------------------------------------------------------- /example/files/yii-1.1.0-validator-cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vernes/YiiMailer/HEAD/example/files/yii-1.1.0-validator-cheatsheet.pdf -------------------------------------------------------------------------------- /example/protected/views/mail/contact.php: -------------------------------------------------------------------------------- 1 |

Message from

2 | 3 |

You may change the content of this page by modifying the following two files:

4 | -------------------------------------------------------------------------------- /example/protected/views/mail/cron.php: -------------------------------------------------------------------------------- 1 |

Message from

2 | 3 |

You may change the content of this page by modifying the following two files:

4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vernes/yiimailer", 3 | "description": "Yii extension for sending emails with layouts using PHPMailer", 4 | "type": "yii-extension", 5 | "require": { 6 | "php": ">=5.5.0", 7 | "phpmailer/phpmailer": "^6.0" 8 | }, 9 | "autoload": { 10 | "classmap": [ 11 | "src" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/protected/config/console.php: -------------------------------------------------------------------------------- 1 | dirname(__FILE__).DIRECTORY_SEPARATOR.'..', 7 | 'name'=>'My Console Application', 8 | 'import'=>array( 9 | 'ext.YiiMailer.YiiMailer', 10 | ), 11 | // application components 12 | 'components'=>array( 13 | 'db'=>array( 14 | 'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db', 15 | ), 16 | // uncomment the following to use a MySQL database 17 | /* 18 | 'db'=>array( 19 | 'connectionString' => 'mysql:host=localhost;dbname=testdrive', 20 | 'emulatePrepare' => true, 21 | 'username' => 'root', 22 | 'password' => '', 23 | 'charset' => 'utf8', 24 | ), 25 | */ 26 | ), 27 | ); -------------------------------------------------------------------------------- /example/protected/yiic.php: -------------------------------------------------------------------------------- 1 | commandRunner->addCommands(YII_PATH.'/cli/commands'); 20 | } 21 | else 22 | $app=Yii::createConsoleApplication(array('basePath'=>dirname(__FILE__).'/cli')); 23 | 24 | $env=@getenv('YII_CONSOLE_COMMANDS'); 25 | if(!empty($env)) 26 | $app->commandRunner->addCommands($env); 27 | 28 | //fix webroot 29 | Yii::setPathOfAlias('webroot',dirname(__FILE__).'/..'); 30 | 31 | $app->run(); -------------------------------------------------------------------------------- /example/protected/views/layouts/mail.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 17 | 18 | 19 | 22 | 23 | 24 | 27 | 28 | 29 |
10 | name); ?> 11 |
15 | 16 |
20 | 21 |
25 | yiiframework.com 26 |
30 | 31 | -------------------------------------------------------------------------------- /example/protected/commands/CronCommand.php: -------------------------------------------------------------------------------- 1 | setView('cron'); 17 | $mail->setData(array('message' => $cronResult, 'name' => get_class($this), 'description' => 'Cron job', 'mailer' => $mail)); 18 | 19 | //set properties 20 | $mail->setFrom('from@example.com', 'Console application'); 21 | $mail->setSubject($cronResult); 22 | $mail->setTo('to@example.com'); 23 | $mail->setAttachment(Yii::getPathOfAlias('webroot.files') . '/yii-1.1.0-validator-cheatsheet.pdf'); 24 | //if you want to use SMTP, configure it in config file or use something like: 25 | $mail->setSmtp('smtp.gmail.com', 465, 'ssl', true, 'your_email@gmail.com', 'your_password'); // GMail example 26 | //send 27 | if ($mail->send()) { 28 | echo 'Mail sent successfuly'; 29 | } else { 30 | echo 'Error while sending email: '.$mail->getError(); 31 | } 32 | echo PHP_EOL; 33 | } 34 | } -------------------------------------------------------------------------------- /example/protected/config/mail.php: -------------------------------------------------------------------------------- 1 | 'application.views.mail', 5 | 'layoutPath' => 'application.views.layouts', 6 | 'baseDirPath' => 'webroot.images.mail', //note: 'webroot' alias in console apps may not be the same as in web apps 7 | 'savePath' => 'webroot.assets.mail', 8 | 'testMode' => false, 9 | 'layout' => 'mail', 10 | 'CharSet' => 'UTF-8', 11 | 'AltBody' => Yii::t('YiiMailer', 'You need an HTML capable viewer to read this message.'), 12 | 'language' => array( 13 | 'authenticate' => Yii::t('YiiMailer', 'SMTP Error: Could not authenticate.'), 14 | 'connect_host' => Yii::t('YiiMailer', 'SMTP Error: Could not connect to SMTP host.'), 15 | 'data_not_accepted' => Yii::t('YiiMailer', 'SMTP Error: Data not accepted.'), 16 | 'empty_message' => Yii::t('YiiMailer', 'Message body empty'), 17 | 'encoding' => Yii::t('YiiMailer', 'Unknown encoding: '), 18 | 'execute' => Yii::t('YiiMailer', 'Could not execute: '), 19 | 'file_access' => Yii::t('YiiMailer', 'Could not access file: '), 20 | 'file_open' => Yii::t('YiiMailer', 'File Error: Could not open file: '), 21 | 'from_failed' => Yii::t('YiiMailer', 'The following From address failed: '), 22 | 'instantiate' => Yii::t('YiiMailer', 'Could not instantiate mail function.'), 23 | 'invalid_address' => Yii::t('YiiMailer', 'Invalid address'), 24 | 'mailer_not_supported' => Yii::t('YiiMailer', ' mailer is not supported.'), 25 | 'provide_address' => Yii::t('YiiMailer', 'You must provide at least one recipient email address.'), 26 | 'recipients_failed' => Yii::t('YiiMailer', 'SMTP Error: The following recipients failed: '), 27 | 'signing' => Yii::t('YiiMailer', 'Signing Error: '), 28 | 'smtp_connect_failed' => Yii::t('YiiMailer', 'SMTP Connect() failed.'), 29 | 'smtp_error' => Yii::t('YiiMailer', 'SMTP server error: '), 30 | 'variable_set' => Yii::t('YiiMailer', 'Cannot set or reset variable: ') 31 | ), 32 | // if you want to use SMTP, uncomment and configure lines below to your needs 33 | // 'Mailer' => 'smtp', 34 | // 'Host' => 'smtp.gmail.com', 35 | // 'Port' => 465, 36 | // 'SMTPSecure' => 'ssl', 37 | // 'SMTPAuth' => true, 38 | // 'Username' => 'your_email@gmail.com', 39 | // 'Password' => 'your_password', 40 | ); 41 | -------------------------------------------------------------------------------- /example/protected/views/site/contact.php: -------------------------------------------------------------------------------- 1 | pageTitle=Yii::app()->name . ' - Contact Us'; 3 | $this->breadcrumbs=array( 4 | 'Contact', 5 | ); 6 | ?> 7 | 8 |

Contact Us

9 | 10 | user->hasFlash('contact')): ?> 11 | 12 |
13 | user->getFlash('contact'); ?> 14 |
15 | 16 | user->hasFlash('error')): ?> 17 | 18 |
19 | user->getFlash('error'); ?> 20 |
21 | 22 | 23 | 24 |

25 | If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. 26 |

27 | 28 |
29 | 30 | beginWidget('CActiveForm', array( 31 | 'id'=>'contact-form', 32 | 'enableClientValidation'=>true, 33 | 'clientOptions'=>array( 34 | 'validateOnSubmit'=>true, 35 | ), 36 | )); ?> 37 | 38 |

Fields with * are required.

39 | 40 | errorSummary($model); ?> 41 | 42 |
43 | labelEx($model,'name'); ?> 44 | textField($model,'name'); ?> 45 | error($model,'name'); ?> 46 |
47 | 48 |
49 | labelEx($model,'email'); ?> 50 | textField($model,'email'); ?> 51 | error($model,'email'); ?> 52 |
53 | 54 |
55 | labelEx($model,'subject'); ?> 56 | textField($model,'subject',array('size'=>60,'maxlength'=>128)); ?> 57 | error($model,'subject'); ?> 58 |
59 | 60 |
61 | labelEx($model,'body'); ?> 62 | textArea($model,'body',array('rows'=>6, 'cols'=>50)); ?> 63 | error($model,'body'); ?> 64 |
65 | 66 | 67 |
68 | labelEx($model,'verifyCode'); ?> 69 |
70 | widget('CCaptcha'); ?> 71 | textField($model,'verifyCode'); ?> 72 |
73 |
Please enter the letters as they are shown in the image above. 74 |
Letters are not case-sensitive.
75 | error($model,'verifyCode'); ?> 76 |
77 | 78 | 79 |
80 | 81 |
82 | 83 | endWidget(); ?> 84 | 85 |
86 | 87 | -------------------------------------------------------------------------------- /example/protected/config/main.php: -------------------------------------------------------------------------------- 1 | dirname(__FILE__).DIRECTORY_SEPARATOR.'..', 10 | 'name'=>'My Web Application', 11 | 12 | // preloading 'log' component 13 | 'preload'=>array('log'), 14 | 15 | // autoloading model and component classes 16 | 'import'=>array( 17 | 'application.models.*', 18 | 'application.components.*', 19 | 'ext.YiiMailer.YiiMailer', 20 | ), 21 | 22 | 'modules'=>array( 23 | // uncomment the following to enable the Gii tool 24 | /* 25 | 'gii'=>array( 26 | 'class'=>'system.gii.GiiModule', 27 | 'password'=>'Enter Your Password Here', 28 | // If removed, Gii defaults to localhost only. Edit carefully to taste. 29 | 'ipFilters'=>array('127.0.0.1','::1'), 30 | ), 31 | */ 32 | ), 33 | 34 | // application components 35 | 'components'=>array( 36 | 'user'=>array( 37 | // enable cookie-based authentication 38 | 'allowAutoLogin'=>true, 39 | ), 40 | // uncomment the following to enable URLs in path-format 41 | /* 42 | 'urlManager'=>array( 43 | 'urlFormat'=>'path', 44 | 'rules'=>array( 45 | '/'=>'/view', 46 | '//'=>'/', 47 | '/'=>'/', 48 | ), 49 | ), 50 | */ 51 | 'db'=>array( 52 | 'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db', 53 | ), 54 | // uncomment the following to use a MySQL database 55 | /* 56 | 'db'=>array( 57 | 'connectionString' => 'mysql:host=localhost;dbname=testdrive', 58 | 'emulatePrepare' => true, 59 | 'username' => 'root', 60 | 'password' => '', 61 | 'charset' => 'utf8', 62 | ), 63 | */ 64 | 'errorHandler'=>array( 65 | // use 'site/error' action to display errors 66 | 'errorAction'=>'site/error', 67 | ), 68 | 'log'=>array( 69 | 'class'=>'CLogRouter', 70 | 'routes'=>array( 71 | array( 72 | 'class'=>'CFileLogRoute', 73 | 'levels'=>'error, warning', 74 | ), 75 | // uncomment the following to show log messages on web pages 76 | /* 77 | array( 78 | 'class'=>'CWebLogRoute', 79 | ), 80 | */ 81 | ), 82 | ), 83 | ), 84 | 85 | // application-level parameters that can be accessed 86 | // using Yii::app()->params['paramName'] 87 | 'params'=>array( 88 | // this is used in contact page 89 | 'adminEmail'=>'webmaster@example.com', 90 | ), 91 | ); -------------------------------------------------------------------------------- /example/protected/controllers/SiteController.php: -------------------------------------------------------------------------------- 1 | array( 13 | 'class'=>'CCaptchaAction', 14 | 'backColor'=>0xFFFFFF, 15 | ), 16 | // page action renders "static" pages stored under 'protected/views/site/pages' 17 | // They can be accessed via: index.php?r=site/page&view=FileName 18 | 'page'=>array( 19 | 'class'=>'CViewAction', 20 | ), 21 | ); 22 | } 23 | 24 | /** 25 | * This is the default 'index' action that is invoked 26 | * when an action is not explicitly requested by users. 27 | */ 28 | public function actionIndex() 29 | { 30 | // renders the view file 'protected/views/site/index.php' 31 | // using the default layout 'protected/views/layouts/main.php' 32 | $this->render('index'); 33 | } 34 | 35 | /** 36 | * This is the action to handle external exceptions. 37 | */ 38 | public function actionError() 39 | { 40 | if($error=Yii::app()->errorHandler->error) 41 | { 42 | if(Yii::app()->request->isAjaxRequest) 43 | echo $error['message']; 44 | else 45 | $this->render('error', $error); 46 | } 47 | } 48 | 49 | /** 50 | * Displays the contact page 51 | */ 52 | public function actionContact() 53 | { 54 | $model=new ContactForm; 55 | if(isset($_POST['ContactForm'])) 56 | { 57 | $model->attributes=$_POST['ContactForm']; 58 | if($model->validate()) 59 | { 60 | //use 'contact' view from views/mail 61 | $mail = new YiiMailer('contact', array('message' => $model->body, 'name' => $model->name, 'description' => 'Contact form')); 62 | 63 | //set properties 64 | $mail->setFrom($model->email, $model->name); 65 | $mail->setSubject($model->subject); 66 | $mail->setTo(Yii::app()->params['adminEmail']); 67 | //send 68 | if ($mail->send()) { 69 | Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.'); 70 | } else { 71 | Yii::app()->user->setFlash('error','Error while sending email: '.$mail->getError()); 72 | } 73 | 74 | $this->refresh(); 75 | } 76 | } 77 | $this->render('contact',array('model'=>$model)); 78 | } 79 | 80 | /** 81 | * Displays the login page 82 | */ 83 | public function actionLogin() 84 | { 85 | $model=new LoginForm; 86 | 87 | // if it is ajax validation request 88 | if(isset($_POST['ajax']) && $_POST['ajax']==='login-form') 89 | { 90 | echo CActiveForm::validate($model); 91 | Yii::app()->end(); 92 | } 93 | 94 | // collect user input data 95 | if(isset($_POST['LoginForm'])) 96 | { 97 | $model->attributes=$_POST['LoginForm']; 98 | // validate user input and redirect to the previous page if valid 99 | if($model->validate() && $model->login()) 100 | $this->redirect(Yii::app()->user->returnUrl); 101 | } 102 | // display the login form 103 | $this->render('login',array('model'=>$model)); 104 | } 105 | 106 | /** 107 | * Logs out the current user and redirect to homepage. 108 | */ 109 | public function actionLogout() 110 | { 111 | Yii::app()->user->logout(); 112 | $this->redirect(Yii::app()->homeUrl); 113 | } 114 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YiiMailer 2 | 3 | Yii (v1.1.x) extension for sending emails with layouts using [PHPMailer](https://github.com/PHPMailer/PHPMailer) 4 | 5 | ## Features 6 | 7 | * Based on PHPMailer 8 | * Supports Yii layouts and translation 9 | * Supports web and console applications 10 | * Send full HTML emails with embedded images 11 | * Work with views like you usually do in Yii 12 | * Use test mode to save emails instead of sending them (useful when you don't have mail server installed locally) 13 | 14 | 15 | ## Installation 16 | 1. Install with composer: `composer require vernes/yiimailer` 17 | 2. Add 'vendor.vernes.yiimailer.YiiMailer' line to your imports in main and/or console yii config 18 | 3. Copy mail.php config file to protected/config or add configuration array in 'params' under the key 'YiiMailer' 19 | 4. Create email layout file mail.php in protected/views/layouts/ (default path, can be changed in config) 20 | 5. Create all the views you want to use in protected/views/mail/ (default path, can be changed in config) 21 | 6. Put all images you want to embed in emails in images/mail/ (default path, can be changed in config) 22 | 23 | ### Note 24 | In console apps, alias 'webroot' may not be the same as in web apps. See https://github.com/yiisoft/yii/issues/1267. 25 | Best workaround is to set alias you need directly in config/console.php, e.g.: 26 |
 27 | Yii::setPathOfAlias('webroot.images.mail', '/path/to/your/images/mail/dir');
 28 | 
29 | 30 | Yet another solution is to override protected/yiic.php and set 'webroot' alias there (see example files). 31 | 32 | ## Usage 33 | 34 | Instantiate YiiMailer in your controller or console command and pass view and data array: 35 |
 36 | $mail = new YiiMailer('contact', array('message' => 'Message to send', 'name' => 'John Doe', 'description' => 'Contact form'));
 37 | 
38 | or 39 |
 40 | $mail = new YiiMailer();
 41 | $mail->setView('contact');
 42 | $mail->setData(array('message' => 'Message to send', 'name' => 'John Doe', 'description' => 'Contact form'));
 43 | 
44 | Layout is automatically set from config but you may override it with 45 |
 46 | $mail->setLayout('layoutName');
 47 | 
48 | 49 | Set the properties: 50 |
 51 | $mail->setFrom('from@example.com', 'John Doe');
 52 | $mail->setTo(Yii::app()->params['adminEmail']);
 53 | $mail->setSubject('Mail subject');
 54 | 
55 | You may use all PHPMailer properties you would usually use. 56 | 57 | And finally send email(s): 58 |
 59 | if ($mail->send()) {
 60 | 	Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');
 61 | } else {
 62 | 	Yii::app()->user->setFlash('error','Error while sending email: '.$mail->getError());
 63 | }
 64 | 
65 | 66 | ### Sending simple messages 67 | 68 | You can send email without both the layout and view by using: 69 |
 70 | $mail = new YiiMailer();
 71 | //$mail->clearLayout();//if layout is already set in config
 72 | $mail->setFrom('from@example.com', 'John Doe');
 73 | $mail->setTo(Yii::app()->params['adminEmail']);
 74 | $mail->setSubject('Mail subject');
 75 | $mail->setBody('Simple message');
 76 | $mail->send();
 77 | 
78 | 79 | Alternatively, you may also send email message with layout but without specific view (set layout and set body) or with view but without layout (clear layout and set view). 80 | 81 | ### Setting addresses 82 | 83 | When using methods for setting addresses (setTo(), setCc(), setBcc(), setReplyTo()) any of the following is valid for arguments: 84 |
 85 | $mail->setTo('john@example.com');
 86 | $mail->setTo(array('john@example.com','jane@example.com'));
 87 | $mail->setTo(array('john@example.com'=>'John Doe','jane@example.com'));
 88 | 
89 | 90 | ### Sending attachments 91 | 92 | You may send one or more attachments using setAttachemnt() method: 93 |
 94 | $mail->setAttachment('something.pdf');
 95 | $mail->setAttachment(array('something.pdf','something_else.pdf','another.doc'));
 96 | $mail->setAttachment(array('something.pdf'=>'Some file','something_else.pdf'=>'Another file'));
 97 | 
98 | 99 | ### Test mode 100 | 101 | When working locally without mail server installed, it may be useful to save emails as files instead of trying to send them and getting errors in the process. 102 | To use test mode, you must specify path to directory where you want to save your emails and set 'testMode' property to 'true' in your config: 103 | 104 |
105 | 	'savePath' => 'webroot.assets.mail',
106 | 	'testMode' => true,
107 | 
108 | 109 | Emails are saved as .eml files and you can use software like Mozilla Thunderbird to open them. 110 | 111 | 112 | ### Using SMTP 113 | 114 | If you want to use SMTP, configure appropriate properties in your config. 115 | Example setup for GMail: 116 |
117 | 	'Mailer' => 'smtp',
118 | 	'Host' => 'smtp.gmail.com',
119 | 	'Port' => 465,
120 | 	'SMTPSecure' => 'ssl',
121 | 	'SMTPAuth' => true,
122 | 	'Username' => 'your_email@gmail.com',
123 | 	'Password' => 'your_password',
124 | 
125 | 126 | You may also configure this just before sending email: 127 |
128 | $mail->setSmtp('smtp.gmail.com', 465, 'ssl', true, 'your_email@gmail.com', 'your_password');
129 | 
130 | 131 | ## Examples 132 | 133 | Two examples included: one for standard contact form in yii web app and the other one for yii console app. 134 | -------------------------------------------------------------------------------- /src/YiiMailer.php: -------------------------------------------------------------------------------- 1 | params[self::CONFIG_PARAMS])) 81 | $config = Yii::app()->params[self::CONFIG_PARAMS]; 82 | else 83 | $config = require(Yii::getPathOfAlias('application.config') . DIRECTORY_SEPARATOR . self::CONFIG_FILE); 84 | //set config 85 | $this->setConfig($config); 86 | //set view 87 | $this->setView($view); 88 | //set data 89 | $this->setData($data); 90 | //set layout 91 | $this->setLayout($layout); 92 | } 93 | 94 | /** 95 | * Configure parameters 96 | * @param array $config Config parameters 97 | * @throws CException 98 | */ 99 | private function setConfig($config) 100 | { 101 | if (!is_array($config)) 102 | throw new CException("Configuration options must be an array!"); 103 | foreach ($config as $key => $val) { 104 | $this->$key = $val; 105 | } 106 | } 107 | 108 | /** 109 | * Set the view to be used 110 | * @param string $view View file 111 | * @param string $type The view type: 'HTML' or 'Text' 112 | * @throws CException 113 | */ 114 | public function setView($view, $type = "HTML") 115 | { 116 | if (!empty($view)) { 117 | if (!is_file($this->getViewFile($this->viewPath . '.' . $view))) 118 | throw new CException('View "' . $view . '" not found'); 119 | 120 | switch ($type) { 121 | case "HTML": 122 | $this->view = $view; 123 | break; 124 | case "Text": 125 | $this->textView = $view; 126 | } 127 | } 128 | } 129 | 130 | /** 131 | * Get currently used view 132 | * @return string HTML View filename 133 | */ 134 | public function getView() 135 | { 136 | return $this->view; 137 | } 138 | 139 | /** 140 | * Set the HTML view to be used 141 | * @param string $view HTML View file 142 | */ 143 | public function setHTMLView($view) 144 | { 145 | $this->setView($view, "HTML"); 146 | } 147 | 148 | /** 149 | * Set the Text view to be used 150 | * @param string $view Text View file 151 | */ 152 | public function setTextView($view) 153 | { 154 | $this->setView($view, "Text"); 155 | } 156 | 157 | /** 158 | * Get currently used text view 159 | * @return string Text View filename 160 | */ 161 | public function getTextView() 162 | { 163 | $this->textView; 164 | } 165 | 166 | /** 167 | * Clear currently used view 168 | */ 169 | public function clearView() 170 | { 171 | $this->view = null; 172 | } 173 | 174 | /** 175 | * Set the alt body text to be applied to $AltBody 176 | * @param string $text 177 | */ 178 | public function setAltText($text = '') 179 | { 180 | $this->altText = $text; 181 | } 182 | 183 | /** 184 | * Get the alt body text to be applied to $AltBody 185 | * @return string the text to be applied to $altBody 186 | */ 187 | public function getAltText() 188 | { 189 | $this->altText; 190 | } 191 | 192 | /** 193 | * Send data to be used in mail body 194 | * @param array $data Data array 195 | */ 196 | public function setData($data) 197 | { 198 | $this->data = $data; 199 | } 200 | 201 | /** 202 | * Get current data array 203 | * @return array Data array 204 | */ 205 | public function getData() 206 | { 207 | return $this->data; 208 | } 209 | 210 | /** 211 | * Clear current data array 212 | */ 213 | public function clearData() 214 | { 215 | $this->data = array(); 216 | } 217 | 218 | /** 219 | * Set layout file to be used 220 | * @param string $layout Layout filename 221 | * @throws CException 222 | */ 223 | public function setLayout($layout) 224 | { 225 | if ($layout != '') { 226 | if (!is_file($this->getViewFile($this->layoutPath . '.' . $layout))) 227 | throw new CException('Layout "' . $layout . '" not found!'); 228 | $this->layout = $layout; 229 | } 230 | } 231 | 232 | /** 233 | * Get current layout 234 | * @return string Layout filename 235 | */ 236 | public function getLayout() 237 | { 238 | return $this->layout; 239 | } 240 | 241 | /** 242 | * Clear current layout 243 | */ 244 | public function clearLayout() 245 | { 246 | $this->layout = null; 247 | } 248 | 249 | /** 250 | * Set path for email views 251 | * @param string $path Yii path 252 | * @throws CException 253 | */ 254 | public function setViewPath($path) 255 | { 256 | if (!is_string($path) && !preg_match("/[a-z0-9\.]/i", $path)) 257 | throw new CException('Path "' . $path . '" not valid!'); 258 | $this->viewPath = $path; 259 | } 260 | 261 | /** 262 | * Get path for email views 263 | * @return string Yii path 264 | */ 265 | public function getViewPath() 266 | { 267 | return $this->viewPath; 268 | } 269 | 270 | /** 271 | * Set path for email layouts 272 | * @param string $path Yii path 273 | * @throws CException 274 | */ 275 | public function setLayoutPath($path) 276 | { 277 | if (!is_string($path) && !preg_match("/[a-z0-9\.]/i", $path)) 278 | throw new CException('Path "' . $path . '" not valid!'); 279 | $this->layoutPath = $path; 280 | } 281 | 282 | /** 283 | * Get path for email layouts 284 | * @return string Yii path 285 | */ 286 | public function getLayoutPath() 287 | { 288 | return $this->layoutPath; 289 | } 290 | 291 | /** 292 | * Set path for images to embed in email messages 293 | * @param string $path Yii path 294 | * @throws CException 295 | */ 296 | public function setBaseDirPath($path) 297 | { 298 | if (!is_string($path) && !preg_match("/[a-z0-9\.]/i", $path)) 299 | throw new CException('Path "' . $path . '" not valid!'); 300 | $this->baseDirPath = $path; 301 | } 302 | 303 | /** 304 | * Get path for email images 305 | * @return string Yii path 306 | */ 307 | public function getBaseDirPath() 308 | { 309 | return $this->baseDirPath; 310 | } 311 | 312 | /** 313 | * Set From address and name 314 | * @param string $address Email address of the sender 315 | * @param string $name Name of the sender 316 | * @param boolean $auto Also set the Reply-To 317 | * @return boolean True on success, false if address not valid 318 | */ 319 | public function setFrom($address, $name = '', $auto = true) 320 | { 321 | return parent::setFrom($address, $name, (bool)$auto); 322 | } 323 | 324 | /** 325 | * Set one or more email addresses to send to 326 | * Valid arguments: 327 | * $mail->setTo('john@example.com'); 328 | * $mail->setTo(array('john@example.com','jane@example.com')); 329 | * $mail->setTo(array('john@example.com'=>'John Doe','jane@example.com')); 330 | * @param mixed $addresses Email address or array of email addresses 331 | * @return boolean True on success, false if addresses not valid 332 | */ 333 | public function setTo($addresses) 334 | { 335 | $this->clearAddresses(); 336 | return $this->setAddresses('to', $addresses); 337 | } 338 | 339 | /** 340 | * Set one or more CC email addresses 341 | * @param mixed $addresses Email address or array of email addresses 342 | * @return boolean True on success, false if addresses not valid 343 | */ 344 | public function setCc($addresses) 345 | { 346 | $this->clearCCs(); 347 | return $this->setAddresses('cc', $addresses); 348 | } 349 | 350 | /** 351 | * Set one or more BCC email addresses 352 | * @param mixed $addresses Email address or array of email addresses 353 | * @return boolean True on success, false if addresses not valid 354 | */ 355 | public function setBcc($addresses) 356 | { 357 | $this->clearBCCs(); 358 | return $this->setAddresses('bcc', $addresses); 359 | } 360 | 361 | /** 362 | * Set one or more Reply-To email addresses 363 | * @param mixed $addresses Email address or array of email addresses 364 | * @return boolean True on success, false if addresses not valid 365 | */ 366 | public function setReplyTo($addresses) 367 | { 368 | $this->clearReplyTos(); 369 | return $this->setAddresses('Reply-To', $addresses); 370 | } 371 | 372 | /** 373 | * Set one or more email addresses of different kinds 374 | * @param string $type Type of the recipient (to, cc, bcc or Reply-To) 375 | * @param mixed $addresses Email address or array of email addresses 376 | * @return boolean True on success, false if addresses not valid 377 | */ 378 | private function setAddresses($type, $addresses) 379 | { 380 | if (!is_array($addresses)) { 381 | $addresses = (array)$addresses; 382 | } 383 | 384 | $result = true; 385 | foreach ($addresses as $key => $value) { 386 | if (is_int($key)) 387 | $r = $this->addAnAddress($type, $value); 388 | else 389 | $r = $this->addAnAddress($type, $key, $value); 390 | if ($result && !$r) 391 | $result = false; 392 | } 393 | 394 | return $result; 395 | } 396 | 397 | /** 398 | * Set subject of the email 399 | * @param string $subject Subject of the email 400 | */ 401 | public function setSubject($subject) 402 | { 403 | $this->Subject = $subject; 404 | } 405 | 406 | /** 407 | * Set text body of the email 408 | * @param string $body Textual body of the email 409 | */ 410 | public function setBody($body) 411 | { 412 | $this->Body = $body; 413 | } 414 | 415 | /** 416 | * Set one or more email attachments 417 | * Valid arguments: 418 | * $mail->setAttachment('something.pdf'); 419 | * $mail->setAttachment(array('something.pdf','something_else.pdf','another.doc')); 420 | * $mail->setAttachment(array('something.pdf'=>'Some file','something_else.pdf'=>'Another file')); 421 | * @param mixed $attachments Path to the file or array of files to attach 422 | * @return boolean True on success, false if addresses not valid 423 | */ 424 | public function setAttachment($attachments) 425 | { 426 | if (!is_array($attachments)) 427 | $attachments = (array)$attachments; 428 | 429 | $result = true; 430 | foreach ($attachments as $key => $value) { 431 | if (is_int($key)) 432 | $r = $this->addAttachment($value); 433 | else 434 | $r = $this->addAttachment($key, $value); 435 | if ($result && !$r) 436 | $result = false; 437 | } 438 | 439 | return $result; 440 | } 441 | 442 | /** 443 | * Clear all recipients and attachments 444 | */ 445 | public function clear() 446 | { 447 | $this->clearAllRecipients(); 448 | $this->clearReplyTos(); 449 | $this->clearAttachments(); 450 | } 451 | 452 | /** 453 | * Get current error message 454 | * @return string Error message 455 | */ 456 | public function getError() 457 | { 458 | return $this->ErrorInfo; 459 | } 460 | 461 | /** 462 | * Find the view file for the given view name 463 | * @param string $viewName Name of the view 464 | * @return string The file path or false if the file does not exist 465 | */ 466 | public function getViewFile($viewName) 467 | { 468 | //In web application, use existing method 469 | if (isset(Yii::app()->controller)) 470 | return Yii::app()->controller->getViewFile($viewName); 471 | //resolve the view file 472 | //TODO: support for themes in console applications 473 | if (empty($viewName)) 474 | return false; 475 | 476 | $viewFile = Yii::getPathOfAlias($viewName); 477 | if (is_file($viewFile . '.php')) 478 | return Yii::app()->findLocalizedFile($viewFile . '.php'); 479 | else 480 | return false; 481 | } 482 | 483 | /** 484 | * Render the view file 485 | * @param string $viewName Name of the view 486 | * @param array $viewData Data for extraction 487 | * @return string The rendered result 488 | * @throws CException 489 | */ 490 | public function renderView($viewName, $viewData = null) 491 | { 492 | //resolve the file name 493 | if (($viewFile = $this->getViewFile($viewName)) !== false) { 494 | //use controller instance if available or create dummy controller for console applications 495 | if (isset(Yii::app()->controller)) 496 | return Yii::app()->controller->renderFile($viewFile, $viewData, true); 497 | else { 498 | $controller = new CController(__CLASS__); 499 | return $controller->renderInternal($viewFile, $viewData, true); 500 | } 501 | } else { 502 | //file name does not exist 503 | throw new CException('View "' . $viewName . '" does not exist!'); 504 | } 505 | 506 | } 507 | 508 | /** 509 | * Generates HTML email, with or without layout 510 | */ 511 | public function render() 512 | { 513 | //render view as body if specified 514 | if (isset($this->view)) 515 | $this->setBody($this->renderView($this->viewPath . '.' . $this->view, $this->data)); 516 | 517 | //render with layout if given 518 | if ($this->layout) { 519 | //has layout 520 | $this->MsgHTMLWithLayout($this->Body, Yii::getPathOfAlias($this->baseDirPath)); 521 | } else { 522 | //no layout 523 | $this->MsgHTML($this->Body, Yii::getPathOfAlias($this->baseDirPath)); 524 | } 525 | 526 | //render alt body if specified 527 | if (isset($this->textView)) { 528 | $this->AltBody = $this->renderView($this->viewPath . '.' . $this->textView, $this->data); 529 | } elseif (isset($this->altText)) { 530 | $this->AltBody = $this->altText; 531 | } 532 | } 533 | 534 | /** 535 | * Render HTML email message with layout 536 | * @param string $message Email message 537 | * @param string $basedir Path for images to embed in message 538 | */ 539 | protected function MsgHTMLWithLayout($message, $basedir = '') 540 | { 541 | $this->msgHTML($this->renderView($this->layoutPath . '.' . $this->layout, array('content' => $message, 'data' => $this->data)), $basedir); 542 | } 543 | 544 | /** 545 | * Render message and send emails 546 | * @return boolean True if sent successfully, false otherwise 547 | */ 548 | public function send() 549 | { 550 | //render message 551 | $this->render(); 552 | 553 | //send the message 554 | try { 555 | //prepare the message 556 | if (!$this->preSend()) 557 | return false; 558 | 559 | //in test mode, save message as a file 560 | if ($this->testMode) 561 | return $this->save(); 562 | else 563 | return $this->postSend(); 564 | } catch (Exception $e) { 565 | $this->mailHeader = ''; 566 | $this->setError($e->getMessage()); 567 | if ($this->exceptions) { 568 | throw $e; 569 | } 570 | return false; 571 | } 572 | } 573 | 574 | /** 575 | * Save message as eml file 576 | * @return boolean True if saved successfully, false otherwise 577 | */ 578 | public function save() 579 | { 580 | $filename = date('YmdHis') . (!empty($this->view) ? '_' . $this->view : '') . '_' . uniqid() . '.eml'; 581 | $dir = Yii::getPathOfAlias($this->savePath); 582 | 583 | // Create a directory 584 | if (!is_dir($dir)) { 585 | $oldmask = @umask(0); 586 | $result = @mkdir($dir, 0777); 587 | @umask($oldmask); 588 | if (!$result) { 589 | throw new CException('Unable to create the directory ' . $dir); 590 | } 591 | } 592 | 593 | try { 594 | $file = fopen($dir . DIRECTORY_SEPARATOR . $filename, 'w+'); 595 | fwrite($file, $this->getSentMIMEMessage()); 596 | fclose($file); 597 | 598 | return true; 599 | } catch (Exception $e) { 600 | $this->setError($e->getMessage()); 601 | 602 | return false; 603 | } 604 | } 605 | 606 | /** 607 | * Setup SMTP and use it to send email 608 | * @param string $host SMTP hosts, either a single hostname or multiple semicolon-delimited hostnames 609 | * @param int $port The default SMTP server port 610 | * @param string $secure The secure connection prefix. Options: "", "ssl" or "tls" 611 | * @param boolean $auth Whether to use SMTP authentication 612 | * @param string $username SMTP username 613 | * @param string $password SMTP password 614 | */ 615 | public function setSmtp($host = 'localhost', $port = 25, $secure = '', $auth = false, $username = '', $password = '') 616 | { 617 | $this->isSMTP(); 618 | $this->Host = $host; 619 | $this->Port = $port; 620 | $this->SMTPSecure = $secure; 621 | $this->SMTPAuth = $auth; 622 | $this->Username = $username; 623 | $this->Password = $password; 624 | } 625 | } 626 | --------------------------------------------------------------------------------