近日在对charsen的修改版上进行了再次的修改与调整,对原版的qee v3 做了更多的bug修改,目前经过测试基本可以使用,虽然还有一些坑,但是代码量始终只有那么一点,填补起来应该很方便,加上qee-v3确实有些技术知识点可供学习..
因为 qee-v3 只给出了一些极简单的库支持,而邮件功能在项目开发过程中又是不可或缺的部分,所以就集成了swiftmailer, 这个库在国外的知名度蛮高的,在性能上比phpmailer要好不少,尤其是对大附件的支持上.唯独的缺陷就是中文文档太少,为了方便使用,故对其做了如下封装....
如果非要对这个封装代码起个名字,那就叫做 qser-mailer 吧
先给出一个如何使用的demo,个人感觉还是比较方便和简单的
class="php" name="code"><?php namespace qser\app\actions; use qeephp\mvc\BaseAction; use qeephp\Config; use qeephp\tools\Logger; use qeephp\storage\mysql\DataSource; use qeephp\storage\Meta; use qser\app\models\Post; use qser\libraries\Validator; use qser\libraries\PinyinLib; class IndexAction extends BaseAction { /** * @var mysql\DataSource */ private $_ds; private $_handle; function execute() { try{ $post5 = Post::find_one(5); } catch( \Exception $ex ) { Logger::instance('test')->fatal($ex); } Logger::instance('test')->debug($post5); dump('indexAction',PinyinLib::topinyin("我爱北京天门")); ///dump($this->app); // $value = 7; // $result = Validator::validateBatch($value, array(array('is_int'),array('between', 2, 6))); // var_dump($result); $this->view(array('action' => 'a', __DIR__)); $email = array('vb@qq.com'); $content = $this->result; $this->app->tool('mail')->mailer->send(function($message) use($email,$content) { $text = $content->execute(); $message->to($email)->subject('qeev3 测试邮件'); $message->setBody($text, 0 ? 'text/plain' : 'text/html'); $message->attachData($text,'runtest',array('as' => $message->encodeAttachmentName('啥都好说'))); $message->attach(MYAPP_SRC_PATH . '/tmp/tests.log',array('as' => $message->encodeAttachmentName('尼玛'))); }); // dump($this->app->tool('mail')->mailer , $email); // //dump( $post5 ); /* $sql = 'show tables'; $result = $this->_ds->execute($sql); dump($result,$sql); // out resource $result = $this->_ds->find_one('post',null); dump($result,'post_one'); $result = $this->_ds->find('post',null)->fetch(); dump($result,'fetch'); $result = $this->_ds->find('post',null)->sort('post_id DESC')->fetch(); dump($result,'fetch by sort'); */ //$result = $this->_ds->find('post',null)->fetch_all(); // dump($result,'fetch_all'); // //$meta = new Meta('qser\\app\\models\\Revision'); //$meta = array(); // dump( $meta ,'meta'); } protected function __before_execute() { // init resource // $this->_ds = new DataSource( Config::get('storage.domains.default') ); // $this->_ds->connect(); // $this->_ds->set_logger(Logger::instance('test')); // $this->_handle = $this->_ds->handle(); // $this->_ds->execute('SET AUTOCOMMIT=0'); // $this->_ds->execute('START TRANSACTION'); // foreach (self::post_recordset() as $post) // { // $this->_ds->insert('qser_posts', $post); // } // $this->_ds->execute('COMMIT'); // $this->_ds->execute('SET AUTOCOMMIT=1'); return true; } // test func static function post_recordset($begin_post_id = 31) { static $authors = array('dualface', 'liaoyulei', 'lownr', 'dox', 'quietlife'); $recordset = array(); for ($post_id = $begin_post_id; $post_id < $begin_post_id + 10; $post_id++) { $author = $authors[mt_rand(0, count($authors) - 1)]; $recordset[$post_id] = array( 'post_id' => $post_id, 'title' => 'post ' . $post_id, 'author' => $author, 'click_count' => mt_rand(1, 999), ); } return $recordset; } static function revisions_recordset($begin_post_id = 1) { $recordset = array(); $created = time(); for ($post_id = $begin_post_id; $post_id < $begin_post_id + 5; $post_id++) { $num_rev = mt_rand(1, 5); for ($i = 0; $i < $num_rev; $i++) { $recordset[] = array( 'post_id' => $post_id, 'body' => sprintf('post %u rev %u', $post_id, $i), 'created' => $created, ); } } return $recordset; } }
?
测试的结果蛮好,如图所示,中文附件名字也能正常显示,灰常给力是不是
------------------------------------------------------------
所有代码如下所示:
<?php namespace qser\app\tools; use qeephp\mvc\App; use qser\libraries\Mail\Mailer; class MailTool { /** * 当前请求 * * @var Mailer */ public $mailer; /** * Create a new Mailer instance. * * @param App $app * @param array $config */ public function __construct(App $app, array $config) { $this->mailer = new Mailer($config); } }
?
<?php namespace qser\libraries\Mail; if (!defined('SWIFT_INIT_LOADED')) { require ROOT_PATH . '/packages/swiftmailer/lib/swift_init.php'; } use Swift_Mailer; use Swift_Message; use qeephp\tools\Logger; use qser\libraries\Mail\Provider; class Mailer { /** * The Swift Mailer instance. * * @var \Swift_Mailer */ protected $swift; /** * The global from address and name. * * @var array */ protected $from; /** * The log writer instance. * * @var ILogger */ protected $logger; /** * Indicates if the actual sending is disabled. * * @var bool */ protected $pretending = false; /** * Array of failed recipients. * * @var array */ protected $failedRecipients = array(); /** * Create a new Mailer instance. * * @param array $config * @return void */ public function __construct(array $config) { $this->swift = Provider::registerSwiftMailer($config); $logger = val($config, 'logger' , false); if ($logger) { $this->setLogger(Logger::instance($logger)); } $from = val($config, 'from' , false); if (is_array($from) && isset($from['address'])) { $this->alwaysFrom($from['address'], $from['name']); } // Here we will determine if the mailer should be in "pretend" mode for this // environment, which will simply write out e-mail to the logs instead of // sending it over the web, which is useful for local dev environments. $pretend = val($config, 'pretend' , false); $this->pretend($pretend); } /** * Set the global from address and name. * * @param string $address * @param string $name * @return void */ public function alwaysFrom($address, $name = null) { $this->from = compact('address', 'name'); } /** * Send a new message. * * @param callback $callback * @return int */ public function send($callback) { $message = $this->createMessage(); $data['message'] = $message; if ($callback && is_callable($callback)) { call_user_func($callback,$message); } else { throw new \InvalidArgumentException('Invalid mail send callback.'); } $message = $message->getSwiftMessage(); return $this->sendSwiftMessage($message); } /** * Send a Swift Message instance. * * @param \Swift_Message $message * @return int */ protected function sendSwiftMessage($message) { if ( !$this->pretending) { return $this->swift->send($message, $this->failedRecipients); } elseif (isset($this->logger)) { $this->logMessage($message); return 1; } } /** * Log that a message was sent. * * @param \Swift_Message $message * @return void */ protected function logMessage($message) { $emails = implode(', ', array_keys((array) $message->getTo())); $this->logger->info("Pretending to mail message to: {$emails}"); } /** * Create a new message instance. * * @return Message */ protected function createMessage() { $message = new Message(new Swift_Message); // If a global from address has been specified we will set it on every message // instances so the developer does not have to repeat themselves every time // they create a new message. We will just go ahead and push the address. if (isset($this->from['address'])) { $message->from($this->from['address'], $this->from['name']); } return $message; } /** * Tell the mailer to not really send messages. * * @param bool $value * @return void */ public function pretend($value = true) { $this->pretending = $value; } /** * Get the Swift Mailer instance. * * @return \Swift_Mailer */ public function getSwiftMailer() { return $this->swift; } /** * Get the array of failed recipients. * * @return array */ public function failures() { return $this->failedRecipients; } /** * Set the log writer instance. * * @param Logger $logger */ public function setLogger(Logger $logger) { $this->logger = $logger; } }
?
<?php namespace qser\libraries\Mail; use Swift_Mailer; use Swift_SmtpTransport as SmtpTransport; use Swift_MailTransport as MailTransport; use Swift_SendmailTransport as SendmailTransport; class Provider { /** * Register the Swift Mailer instance. * * @return \Swift_Mailer */ public static function registerSwiftMailer($config) { $self = new static(); return new Swift_Mailer( $self->registerSwiftTransport($config) ); } /** * Register the Swift Transport instance. * * @param array $config * @return void * * @throws \InvalidArgumentException */ protected function registerSwiftTransport($config) { switch ($config['driver']) { case 'smtp': return $this->registerSmtpTransport($config); case 'sendmail': return $this->registerSendmailTransport($config); case 'mail': return $this->registerMailTransport($config); default: throw new \InvalidArgumentException('Invalid mail driver.'); } } /** * Register the SMTP Swift Transport instance. * * @param array $config * @return void */ protected function registerSmtpTransport($config) { // The Swift SMTP transport instance will allow us to use any SMTP backend // for delivering mail such as Sendgrid, Amazon SMS, or a custom server // a developer has available. We will just pass this configured host. $transport = SmtpTransport::newInstance($config['host'], $config['port']); if (!empty($config['encryption'])) { $transport->setEncryption($config['encryption']); } // Once we have the transport we will check for the presence of a username // and password. If we have it we will set the credentials on the Swift // transporter instance so that we'll properly authenticate delivery. if (!empty($config['username'])) { $transport->setUsername($config['username']); $transport->setPassword($config['password']); } return $transport; } /** * Register the Sendmail Swift Transport instance. * * @param array $config * @return void */ protected function registerSendmailTransport($config) { return SendmailTransport::newInstance($config['sendmail']); } /** * Register the Mail Swift Transport instance. * * @param array $config * @return void */ protected function registerMailTransport($config) { return MailTransport::newInstance(); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return array('mailer', 'swift.mailer', 'swift.transport'); } }
?
<?php namespace qser\libraries\Mail; use Swift_Image; use Swift_Attachment; class Message { /** * The Swift Message instance. * * @var \Swift_Message */ protected $swift; /** * Create a new message instance. * * @param \Swift_Message $swift * @return void */ public function __construct($swift) { $this->swift = $swift; } /** * Add a "from" address to the message. * * @param string $address * @param string $name * @return \qser\libraries\Mail\Message */ public function from($address, $name = null) { $this->swift->setFrom($address, $name); return $this; } /** * Set the "sender" of the message. * * @param string $address * @param string $name * @return \qser\libraries\Mail\Message */ public function sender($address, $name = null) { $this->swift->setSender($address, $name); return $this; } /** * Set the "return path" of the message. * * @param string $address * @return \qser\libraries\Mail\Message */ public function returnPath($address) { $this->swift->setReturnPath($address); return $this; } /** * Add a recipient to the message. * * @param string|array $address * @param string $name * @return \qser\libraries\Mail\Message */ public function to($address, $name = null) { return $this->addAddresses($address, $name, 'To'); } /** * Add a carbon copy to the message. * * @param string $address * @param string $name * @return \qser\libraries\Mail\Message */ public function cc($address, $name = null) { return $this->addAddresses($address, $name, 'Cc'); } /** * Add a blind carbon copy to the message. * * @param string $address * @param string $name * @return \qser\libraries\Mail\Message */ public function bcc($address, $name = null) { return $this->addAddresses($address, $name, 'Bcc'); } /** * Add a reply to address to the message. * * @param string $address * @param string $name * @return \qser\libraries\Mail\Message */ public function replyTo($address, $name = null) { return $this->addAddresses($address, $name, 'ReplyTo'); } /** * Add a recipient to the message. * * @param string|array $address * @param string $name * @param string $type * @return \qser\libraries\Mail\Message */ protected function addAddresses($address, $name, $type) { if (is_array($address)) { $this->swift->{"set{$type}"}($address, $name); } else { $this->swift->{"add{$type}"}($address, $name); } return $this; } /** * Set the subject of the message. * * @param string $subject * @return \qser\libraries\Mail\Message */ public function subject($subject) { $this->swift->setSubject($subject); return $this; } /** * Set the message priority level. * * @param int $level * @return \qser\libraries\Mail\Message */ public function priority($level) { $this->swift->setPriority($level); return $this; } /** * 编码附件名称(可用于显示中文附件名) * * @param string $file * * @return string */ public function encodeAttachmentName($name) { return "=?UTF-8?B?" . base64_encode($name) . "?="; } /** * Attach a file to the message. * * @param string $file * @param array $options * @return \qser\libraries\Mail\Message */ public function attach($file, array $options = array()) { $attachment = $this->createAttachmentFromPath($file); return $this->prepAttachment($attachment, $options); } /** * Create a Swift Attachment instance. * * @param string $file * @return \Swift_Attachment */ protected function createAttachmentFromPath($file) { return Swift_Attachment::fromPath($file); } /** * Attach in-memory data as an attachment. * * @param string $data * @param string $name * @param array $options * @return \qser\libraries\Mail\Message */ public function attachData($data, $name, array $options = array()) { $attachment = $this->createAttachmentFromData($data, $name); return $this->prepAttachment($attachment, $options); } /** * Create a Swift Attachment instance from data. * * @param string $data * @param string $name * @return \Swift_Attachment */ protected function createAttachmentFromData($data, $name) { return Swift_Attachment::newInstance($data, $name); } /** * Embed a file in the message and get the CID. * * @param string $file * @return string */ public function embed($file) { return $this->swift->embed(Swift_Image::fromPath($file)); } /** * Embed in-memory data in the message and get the CID. * * @param string $data * @param string $name * @param string $contentType * @return string */ public function embedData($data, $name, $contentType = null) { $image = Swift_Image::newInstance($data, $name, $contentType); return $this->swift->embed($image); } /** * Prepare and attach the given attachment. * * @param \Swift_Attachment $attachment * @param array $options * @return \qser\libraries\Mail\Message */ protected function prepAttachment($attachment, $options = array()) { // First we will check for a MIME type on the message, which instructs the // mail client on what type of attachment the file is so that it may be // downloaded correctly by the user. The MIME option is not required. if (isset($options['mime'])) { $attachment->setContentType($options['mime']); } // If an alternative name was given as an option, we will set that on this // attachment so that it will be downloaded with the desired names from // the developer, otherwise the default file names will get assigned. if (isset($options['as'])) { $attachment->setFilename($options['as']); } $this->swift->attach($attachment); return $this; } /** * Get the underlying Swift Message instance. * * @return \Swift_Message */ public function getSwiftMessage() { return $this->swift; } /** * Dynamically pass missing methods to the Swift instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { $callable = array($this->swift, $method); return call_user_func_array($callable, $parameters); } }
?
?
?
-------- 配置信息如下所示
?
?