├── .gitignore ├── logs └── .gitignore ├── .gitattributes ├── screenshot.png ├── README.md ├── guest.html ├── owner1.html ├── owner.html ├── guest1.html └── Plugin.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /logs/.gitignore: -------------------------------------------------------------------------------- 1 | *_log.php 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-language=PHP 2 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oott123/CommentMailPlus/HEAD/screenshot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CommentMailPlus 2 | 3 | ## 评论邮件通知插件 4 | 5 | 一款 Typecho 评论邮件提醒插件 6 | 7 | - 基于 PHP 插件 cURL 实现 8 | - 基于 MailGun API 实现 9 | 10 | ### 安装方法 11 | 12 | 进入插件目录 13 | 14 | ```bash 15 | $ cd typecho/usr/plugins/ 16 | ``` 17 | 18 | > 小贴士:此处路径请根据实际网址路径进行调整,此处仅为样例。 19 | 20 | 克隆插件文件 21 | 22 | ```bash 23 | $ git clone https://github.com/oott123/CommentMailPlus.git 24 | ``` 25 | 26 | 在后台启用即可 27 | 28 | ### 适用环境 29 | 30 | 本插件发送邮件利用 cURL 组件连接 MailGun 的 HTTPS 接口,具有到达率高,延迟低等特点,适合于无法使用 SMTP 的环境使用。 31 | 32 | 若当前 PHP 环境无法修改以支持 cURL 组件,可以尝试使用 [CommentToMail](http://docs.typecho.org/plugins/commenttomail) 插件,然后参照 [MailGun User Manual](https://documentation.mailgun.com/en/latest/user_manual.html#introduction) 上的相关说明设置 SMTP 服务。 33 | 34 | 经测试,SAE可用。 35 | 36 | ### 感谢 37 | 38 | [@Cain](https://github.com/Vndroid) 39 | 40 | ### 其它问题 41 | 42 | 有问题请发 issues ,欢迎提交代码。其他关于 MailGun 说明可在[官方文档](https://documentation.mailgun.com/en/latest/)中查看。 -------------------------------------------------------------------------------- /guest.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
来自 {site} 的回应
{author}回复:
{text}
回复地址:{permalink}
{author_p}的原文:
{text_p}
本邮件为{site}自动发送,请勿回复!
21 |
-------------------------------------------------------------------------------- /owner1.html: -------------------------------------------------------------------------------- 1 |
5 |
8 | {site}:《{title}》有新的评论 9 |
10 |
11 |

作者:{author} <{mail}>

12 |

时间:{time}

13 |

内容:

14 |

{text}

16 | 17 |

您可以点击 查看回复的完整內容

18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /owner.html: -------------------------------------------------------------------------------- 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 |
{site}:《{title}》有新的评论
作者:{author} {mail}
时间:{time}
状态:{status} [管理评论]
链接:{permalink}
内容:
{text}
本邮件为{site}自动发送,请勿回复!
27 |
-------------------------------------------------------------------------------- /guest1.html: -------------------------------------------------------------------------------- 1 |
5 |
8 | 您在{site} 博客上的留言有回复啦! 9 |
10 |
11 |

{author_p}, 您好!

12 |

您曾在 [{site}] 的文章《{title}》上发表评论: 13 |

{text_p}

15 |

{author} 给您的回复如下: 16 |

{text}

18 |

您可以点击 查看回复的完整內容

19 |

欢迎再次光临 {site}

20 |
21 |
22 | -------------------------------------------------------------------------------- /Plugin.php: -------------------------------------------------------------------------------- 1 | finishComment = array('CommentMailPlus_Plugin', 'toMail'); 24 | return _t('请到设置面板正确配置 MailGun 才可正常工作。'); 25 | } 26 | 27 | /** 28 | * 禁用插件方法,如果禁用失败,直接抛出异常 29 | * 30 | * @static 31 | * @access public 32 | * @return void 33 | * @throws Typecho_Plugin_Exception 34 | */ 35 | public static function deactivate() { 36 | Helper::removeAction('comment-mail-plus'); 37 | } 38 | 39 | /** 40 | * 获取插件配置面板 41 | * 42 | * @access public 43 | * @param Typecho_Widget_Helper_Form $form 配置面板 44 | * @return void 45 | */ 46 | public static function config(Typecho_Widget_Helper_Form $form) { 47 | $mail = new Typecho_Widget_Helper_Form_Element_Text('mail', NULL, NULL, 48 | _t('收件人邮箱'),_t('接收邮件用的信箱,为空则使用文章作者个人设置中的邮箱!')); 49 | $form->addInput($mail->addRule('email', _t('请填写正确的邮箱!'))); 50 | 51 | $status = new Typecho_Widget_Helper_Form_Element_Checkbox('status', 52 | array('approved' => '提醒已通过评论', 53 | 'waiting' => '提醒待审核评论', 54 | 'spam' => '提醒垃圾评论'), 55 | array('approved', 'waiting'), '提醒设置',_t('该选项仅针对博主,访客只发送已通过的评论。')); 56 | $form->addInput($status); 57 | 58 | $other = new Typecho_Widget_Helper_Form_Element_Checkbox('other', 59 | array('to_owner' => '有评论及回复时,发邮件通知博主', 60 | 'to_guest' => '评论被回复时,发邮件通知评论者', 61 | 'to_me'=>'自己回复自己的评论时(同时针对博主和访客),发邮件通知', 62 | 'to_log' => '记录邮件发送日志'), 63 | array('to_owner','to_guest'), '其他设置',_t('如果勾选“记录邮件发送日志”选项,则会在 ./CommentMailPlus/logs/mail_log.php 中记录发送信息。
64 | 关键性错误日志将自动记录到 ./CommentMailPlus/logs/error_log.php 中。
65 | ')); 66 | $form->addInput($other->multiMode()); 67 | $key = new Typecho_Widget_Helper_Form_Element_Text('key', NULL, 'xxxxxxxxxxxxxxxxxxx-xxxxxx-xxxxxx', 68 | _t('MailGun API 密钥'), _t('请填写在 MailGun 申请的密钥,可在个人页中查看 ')); 69 | $form->addInput($key->addRule('required', _t('密钥不能为空'))); 70 | $domain = new Typecho_Widget_Helper_Form_Element_Text('domain', NULL, 'samples.mailgun.org', 71 | _t('MailGun 域名'), _t('请填写您的邮件域名,若使用官方提供的测试域名可能存在其他问题')); 72 | $form->addInput($domain->addRule('required', _t('邮件域名不能为空'))); 73 | $mailAddress = new Typecho_Widget_Helper_Form_Element_Text('mailAddress', NULL, 'no-reply@samples.mailgun.org', 74 | _t('发件人邮箱')); 75 | $form->addInput($mailAddress->addRule('required', _t('发件人地址不能为空'))); 76 | $senderName = new Typecho_Widget_Helper_Form_Element_Text('senderName', NULL, '评论提醒', 77 | _t('发件人显示名')); 78 | $form->addInput($senderName); 79 | 80 | $titleForOwner = new Typecho_Widget_Helper_Form_Element_Text('titleForOwner',null,"[{site}]:《{title}》有新的评论", 81 | _t('博主接收邮件标题')); 82 | $form->addInput($titleForOwner); 83 | 84 | $titleForGuest = new Typecho_Widget_Helper_Form_Element_Text('titleForGuest',null,"[{site}]:您在《{title}》的评论有了回复", 85 | _t('访客接收邮件标题')); 86 | $form->addInput($titleForGuest); 87 | } 88 | 89 | /** 90 | * 个人用户的配置面板 91 | * 92 | * @access public 93 | * @param Typecho_Widget_Helper_Form $form 94 | * @return void 95 | */ 96 | public static function personalConfig(Typecho_Widget_Helper_Form $form) { 97 | 98 | } 99 | 100 | /** 101 | * 组合邮件内容 102 | * 103 | * @access public 104 | * @param $post 调用参数 105 | * @return void 106 | */ 107 | public static function toMail($post) { 108 | //发送邮件 109 | $settings=Helper::options()->plugin('CommentMailPlus'); 110 | $options = Typecho_Widget::widget('Widget_Options'); 111 | //邮件模板变量 112 | $tempinfo['site'] = $options->title; 113 | $tempinfo['siteUrl'] = $options->siteUrl; 114 | $tempinfo['title'] = $post->title; 115 | $tempinfo['cid'] = $post->cid; 116 | $tempinfo['coid'] = $post->coid; 117 | $tempinfo['created'] = $post->created; 118 | $tempinfo['timezone'] = $options->timezone; 119 | $tempinfo['author'] = $post->author; 120 | $tempinfo['authorId'] = $post->authorId; 121 | $tempinfo['ownerId'] = $post->ownerId; 122 | $tempinfo['mail'] = $post->mail; 123 | $tempinfo['ip'] = $post->ip; 124 | $tempinfo['title'] = $post->title; 125 | $tempinfo['text'] = $post->text; 126 | $tempinfo['permalink'] = $post->permalink; 127 | $tempinfo['status'] = $post->status; 128 | $tempinfo['parent'] = $post->parent; 129 | $tempinfo['manage'] = $options->siteUrl."admin/manage-comments.php"; 130 | $_db = Typecho_Db::get(); 131 | $original = $_db->fetchRow($_db::get()->select('author', 'mail', 'text') 132 | ->from('table.comments') 133 | ->where('coid = ?', $tempinfo['parent'])); 134 | //var_dump($original);die(); 135 | 136 | //判断发送 137 | //1.发送博主邮件 138 | //无需判断,先发为敬。 139 | if(in_array('to_owner', $settings->other) && in_array($tempinfo['status'], $settings->status)){ 140 | $this_mail = $tempinfo['mail']; 141 | $to_mail = $settings->mail; 142 | if(!$to_mail){ 143 | Typecho_Widget::widget('Widget_Users_Author@' . $tempinfo['cid'], array('uid' => $tempinfo['authorId']))->to($user); 144 | $to_mail = $user->mail; 145 | } 146 | if($this_mail != $to_mail || in_array('to_me',$settings->other)){ 147 | //判定可以发送邮件 148 | $from_mail = $settings->mailAddress; 149 | $title = self::_getTitle(false,$settings,$tempinfo); 150 | $body = self::_getHtml(false,$tempinfo); 151 | self::_sendMail($to_mail,$from_mail,$title,$body,$settings); 152 | } 153 | } 154 | //2.发送评论者邮件 155 | //判断是否为回复评论,是则发,否则跳。 156 | if (!empty($original)){ 157 | $tempinfo['originalMail'] = $original['mail']; 158 | $tempinfo['originalText'] = $original['text']; 159 | $tempinfo['originalAuthor'] = $original['author']; 160 | if(in_array('to_guest', $settings->other) && 'approved'==$tempinfo['status'] && $tempinfo['originalMail']){ 161 | $to_mail = $tempinfo['originalMail']; 162 | $from_mail = $settings->mailAddress; 163 | $title = self::_getTitle(true,$settings,$tempinfo); 164 | $body = self::_getHtml(true,$tempinfo); 165 | self::_sendMail($to_mail,$from_mail,$title,$body,$settings); 166 | } 167 | } 168 | 169 | } 170 | public static function _getTitle($toGuest,$settings,$tempinfo){ 171 | //获取发送标题 172 | $title = ''; 173 | if($toGuest){ 174 | $title = $settings->titleForGuest; 175 | }else{ 176 | $title = $title = $settings->titleForOwner; 177 | } 178 | return str_replace(array('{title}','{site}'), array($tempinfo['title'],$tempinfo['site']), $title); 179 | } 180 | public static function _getHtml($toGuest,$tempinfo){ 181 | //获取发送模板 182 | $dir = dirname(__FILE__).'/'; 183 | $time = date("Y-m-d H:i:s",$tempinfo['created']+$tempinfo['timezone']); 184 | $search=$replace=array(); 185 | if($toGuest){ 186 | $dir.='guest.html'; 187 | $search = array('{site}','{siteUrl}', '{title}','{author_p}','{author}','{mail}','{permalink}','{text}','{text_p}','{time}'); 188 | $replace = array($tempinfo['site'],$tempinfo['siteUrl'],$tempinfo['title'],$tempinfo['originalAuthor'],$tempinfo['author'], $tempinfo['mail'],$tempinfo['permalink'],$tempinfo['text'],$tempinfo['originalText'],$time); 189 | }else{ 190 | $dir.='owner.html'; 191 | $status = array( 192 | "approved" => '通过', 193 | "waiting" => '待审', 194 | "spam" => '垃圾' 195 | ); 196 | $search = array('{site}','{siteUrl}', '{title}','{author}','{ip}','{mail}','{permalink}','{manage}','{text}','{time}','{status}'); 197 | $replace = array($tempinfo['site'],$tempinfo['siteUrl'],$tempinfo['title'],$tempinfo['author'],$tempinfo['ip'],$tempinfo['mail'],$tempinfo['permalink'],$tempinfo['manage'],$tempinfo['text'],$time,$status[$tempinfo['status']]); 198 | } 199 | $html = file_get_contents($dir); 200 | return str_replace($search, $replace, $html); 201 | } 202 | public static function _sendMail($to_mail,$from_mail,$title,$body,$settings){ 203 | //发送邮件 204 | //self::_log($to_mail,'debug');return; 205 | $api_key = $settings->key; 206 | $domain = $settings->domain; 207 | $from_mail = $settings->senderName.' <'.$from_mail.'>'; 208 | $postData = array( 209 | 'from' => $from_mail, 210 | 'to' => $to_mail, 211 | 'subject' => $title, 212 | 'html' => $body, 213 | ); 214 | $url = 'https://api.mailgun.net/v3/'.$domain.'/messages'; 215 | $ch = curl_init(); 216 | curl_setopt($ch, CURLOPT_USERPWD,'api:'.$api_key); 217 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 218 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 219 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 220 | curl_setopt($ch, CURLOPT_POST, true); 221 | curl_setopt($ch, CURLOPT_URL, $url); 222 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 223 | curl_setopt($ch, CURLOPT_HEADER, true); 224 | self::_log('curl prepareing...'.print_r(curl_getinfo($ch),1),'debug'); 225 | $result = curl_exec($ch); 226 | self::_log('API return...'.$result,'debug'); 227 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 228 | $result = substr($result, $headerSize); 229 | $res = json_decode($result,1); 230 | self::_log('curl excuted...'.print_r(curl_getinfo($ch),1),'debug'); 231 | self::_log($to_mail.' '.'Sending: '.$res['message']); 232 | } 233 | public static function _log($msg,$file='error'){ 234 | //记录日志 235 | $settings=Helper::options()->plugin('CommentMailPlus'); 236 | if(!in_array('to_log', $settings->other)) return false; 237 | //开发者模式 238 | if($file=='debug' && true) return false; 239 | $filename = dirname(__FILE__).'/logs/'.$file.'_log.php'; 240 | if(!is_file($filename)){ 241 | file_put_contents($filename, '