php 使用msmtp发送邮件

08月 19th, 2008

网站通过内置服务器发给用户的邮件,经常被用户客户端默认为垃圾邮件。
这是一个很头痛的问题。我曾经试过设置各种各样的邮件头部,都没能逃脱这个厄运。现在可行的方法是通过php直接访问一些专门smtp服务器把邮件发送出去。gmail就是一个不错的选择,还支持自定义域名。
msmtp是一个命令行的smtp客户端,在php.ini 设置:
sendmail_path = “/opt/local/bin/msmtp –file=/xxx/.msmtprc -t”
即可通过php mail()函数来发送邮件,这个比直接用php来访问smtp好得多。

ps:
msmtp 安装设置可参考 这里
gmail 发送邮件人数不能超过100.原文如下:
“You can send a single message to a maximum of 500 recipients through the web interface, or up to 100 recipients when using POP access. Their email addresses can be distributed among the To, Cc, and Bcc fields.”

php mail 测试代码:

  1. <?php
  2. $to  = 'receive ';
  3. $subject = 'Test Msmtp';
  4.  
  5. $message = 'Here is test';
  6.  
  7. $headers  = 'MIME-Version: 1.0' . "\r\n";
  8. $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
  9. $headers .= 'From: gmail ' . "\r\n";
  10.  
  11. $start = microtime(TRUE);
  12. var_dump(mail($to, $subject, $message, $headers));
  13. echo '
  14. ', "\n", microtime(true) - $start;
  15. ?>

msmtp 安装手记

08月 19th, 2008

msmtp是一个命令行的smtp客户端。可是php等脚本调用。
使用默认邮件服务器发送邮件容易被当作垃圾邮件,如果执行使用php进行smtp邮件发送效率太低。msmtp可以作为中介,在google申请一个企业邮箱专门用于网站发邮件,还不用担心邮件被用户当垃圾邮件。
本安装方法在Mac OS leopard操作系统下测试成功。
1.安装MacPort
请到http://www.macports.org下载最新MacPort安装包。
MacPort
macport会默认安装到/opt/local/bin目录下。
2.打开一个shell窗口:
shell

执行echo $SHELL。
如果bash shell 则执行
echo “export PATH=$PATH:/opt/local/bin” >> ~/.profile
重新开启bash shell使设置变量生效。
3. 执行 sudo port intall msmtp
msmtp安装完成后,执行 touch ~/.msmtprc
以下为.msmtprc的模板:
#Set default values for all following accounts
defaults
tls on
tls_trust_file ~/msmtp/ca-certificates.crt
logfile ~/msmtp/msmtplog

# Gmail service
account gmail
host smtp.gmail.com
from xxx@gmail.com
auth on
user xxxx
password xxxxxx
#port 587                 #可要可不要的

# A freemail service
#account freemail
#host smtp.freemail.example
#from joe_smith@freemail.example
#auth on
#user joe.smith
#password secret

# A second mail address at the same freemail service
#account freemail2 : freemail
#from joey@freemail.example

# The SMTP server of the provider.
#account provider
#host mail.provider.example
#from smithjoe@provider.example
#auth on
#user 123456789
#password my_password
# Set a default account
account default : gmail

4. 下载证书文件

https://www.verisign.com/support/thawte-roots.zip
mkdir ~/msmtp

解压后
mv thawte-roots/Thawte Server Roots/ThawtePremiumServerCA_b64.txt ~/msmtp/ca-certificates.crt
5. 测试
msmtp xxxx@comsenz.com
按clt + D 结束即可。
查看~/msmtp/msmtplog看是否发送成功

js缓存类 Storage.js

07月 9th, 2008

这个是可以将用户数据缓存到本地浏览器.据说可以缓存100k以上数据,支持ie,firefox2以上,不占用cookie.当cookie 数据太大时这个可以是首选.
以下是Web boyecmall 写的一个缓存类.
写得很优美的一个类. 所有方法使用动态绑定.在确认浏览器后才把对应的方法绑定上去.
该类使用了ecmall自己的框架,我把涉及的部分都放到Storage类后面.该类还缺一个json解析类,可以自己去找.

下载: Storage.js
  1. var Storage = new Object();
  2. Object.extend(Storage, (function(){
  3.   var _storage = false;
  4.   if (navigator.isIE()) document.documentElement.addBehavior("#default#userdata");
  5.   if (typeof(sessionStorage) != 'undefined') _storage = sessionStorage;
  6.  
  7.   if (navigator.isIE()){
  8.     var _add = function(key, value){
  9.       with(document.documentElement) 
  10.       try {
  11.         load(key);
  12.         setAttribute("value", value);
  13.         save(key);
  14.         return  getAttribute("value");
  15.       } catch (ex){
  16.         return null;
  17.       }
  18.     };
  19.    
  20.     var _get = function(key) {
  21.       with(document.documentElement)
  22.       try {
  23.         load(key);
  24.         return  getAttribute("value");
  25.       } catch (ex){
  26.         return null;
  27.       }
  28.     };
  29.    
  30.     var _remove = function(key) {
  31.       with(document.documentElement)
  32.       try {
  33.         load(key);
  34.         removeAttribute("value")
  35.         save(key);
  36.       } catch(ex){}
  37.     };
  38.    
  39.   } else if(navigator.isFirefox() && _storage){
  40.     var _add = function(key, value){
  41.       sessionStorage.setItem(key,value);
  42.     };
  43.  
  44.     var _get = function(key) {
  45.       return sessionStorage.getItem(key)
  46.     };
  47.    
  48.     var _remove = function(key) {
  49.       var value = undefined;
  50.       sessionStorage.setItem(key,value);
  51.     };
  52.   } else {
  53.     var _add = function(key, value){
  54.       document.setCookie(key, value);
  55.     };
  56.  
  57.     var _get = function(key) {
  58.       return document.getCookie(key);
  59.     };
  60.    
  61.     var _remove = function(key) {
  62.       document.removeCookie(key);
  63.     };
  64.   }
  65.  
  66.   return {
  67.     add: function(key, value) {
  68.       if (typeof(value) != 'string') {
  69.         value = value.toJSONString();
  70.       }
  71.       _add(key, value);
  72.     },
  73.     get: function(key){
  74.       return _get(key);
  75.     },
  76.     remove: function(key){
  77.       _remove(key);
  78.     }
  79.   };
  80. })());

ecmall 框架截取

下载: ecmall.js
  1. Object.extend = function(destination, source){
  2.   for (property in source)
  3.     destination[property] = source[property];
  4.   return destination;
  5. };
  6.  
  7.  
  8. /* Navigator Extensions */
  9. Object.extend(navigator, {
  10.   isIE : function() { return this.userAgent.toLowerCase().indexOf("msie") != - 1; },
  11.   isFirefox : function() { return this.userAgent.toLowerCase().indexOf("firefox") != - 1; },
  12.   isSafari : function() { return this.userAgent.toLowerCase().indexOf("safari") != - 1; },
  13.   isOpera : function() { return this.userAgent.toLowerCase().indexOf("opera") != - 1; }
  14. });
  15.  
  16.  
  17. /* Document Extensions */
  18. Object.extend(document, {
  19.   getCookie : function(sName) {
  20.     var aCookie = this.cookie.split("; ");
  21.     for (var i=0; i < aCookie.length; i++){
  22.       var aCrumb = aCookie[i].split("=");
  23.       if (sName == aCrumb[0]) return decodeURIComponent(aCrumb[1]);
  24.     }
  25.     return null;
  26.   },
  27.  
  28.   setCookie : function(sName, sValue, sExpires) {
  29.     var sCookie = sName + "=" + encodeURIComponent(sValue);
  30.     if (sExpires != null) sCookie += "; expires=" + sExpires;
  31.     this.cookie = sCookie;
  32.   },
  33.  
  34.   removeCookie : function(sName) {
  35.     this.cookie = sName + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
  36.   },
  37.  
  38.   require : function(path, callback, type){
  39.     var s,i;
  40.     var id = path.replace(".","").replace("/","");
  41.  
  42.     if (!type || type == "js"){
  43.       var ss = this.getElementsByTagName("script");
  44.       for(i =0;i < ss.length; i++){
  45.         if(ss[i].src && ss[i].src.indexOf(path) != -1)return ss[i];
  46.       }
  47.  
  48.       s      = $ce("script");
  49.       s.id   = id;
  50.       s.type = "text/javascript";
  51.       s.src  = path;
  52.     }
  53.     else {
  54.       var ss = this.getElementsByTagName("link");
  55.       for(i =0;i < ss.length; i++){
  56.         if(ss[i].src && ss[i].src.indexOf(path) != -1)return ss[i];
  57.       }
  58.  
  59.       s = $ce("link");
  60.       s = document.createElement("link");
  61.       s.rel = "stylesheet";
  62.       s.type = "text/css";
  63.       s.href = path;
  64.       s.disabled = false;
  65.     }
  66.     var head = this.getElementsByTagName("head")[0];
  67.     head.appendChild(s);
  68.     if (callback) {
  69.       if (!navigator.isIE() && type == "css") {
  70.         window.setTimeout(function(){callback.call()}, 100);
  71.       }
  72.       else {
  73.         s.onload = s.onreadystatechange= function(){
  74.           if(this.readyState && this.readyState=="loading")return;
  75.           callback.call();
  76.         }
  77.       }
  78.     }
  79.   }
  80. });

对以前日志的默哀

07月 1st, 2008

一次失误导致以前日志全部被毁。
这是一个意想不到的失误。我用phpmyadmin备份了7月以前数据,然后恢复时发现全变乱码了。查了很多资料都没能恢复。以下是备份文件截图:

希望我的失误能使大家引以为戒。phpmyadmin导出数据一定要选对编码。对导出文件最后手工检查下是否有问题,不然再导入时就追悔莫及了。