八月
7

PHPMailer类发送中文邮件兼谈解决XOOPS中文发送邮件乱码

Author Dominic    Category PHP, XOOPS     Tags ,

.org.cn论坛上又有人问xoops发送中文邮件乱码的问题。domecc给出了一个临时办法,还提供一个网址http://www.thedevlog.com/dev/log-29.html来对utf8编码系统做修正。

其实PHPMailer已经是非常成熟的PHP类了(当然需要打上前一段时间出现的bug的补丁),对于邮件头和邮件体的编码处理已经非常好了,http://www.thedevlog.com/dev/log-29.html中提到修改EncodeHeader并编码,实际上EncodeHeader后面的代码就是完成将头部编码的功能,所以不需要修改该函数。

要成功实现发送中文邮件,设置phpmailer类两个值即可。

$mail = new PHPMailer();
$mail->CharSet = “UTF-8″; // 设置字符集编码,GB2312 GBK
$mail->Encoding = “base64″;//设置文本编码方式
……

这样保证了邮件标题和正文内容全部不会乱码,当然邮件内容的字符集需要和给定的CharSet内容一致。

回过头来看看xoops中为什么邮件乱码,在xoops中发送邮件首先我们使用了具体语言的xoopsmailerlocal.php文件中XoopsMailerLocal类,而XoopsMailerLocal类继承自class\xoopsmailer.php中的XoopsMailer类,而XoopsMailer类的multimailer成员指向自class\mail\xoopsmultimailer.php中的XoopsMultiMailer类的实体,XoopsMultiMailer类是从PHPMailer派生的。

问题就出在XoopsMailer的构造函数上。在XoopsMultiMailer类的构造函数中(xoopsmultimailer.php中177行)指定了CharSet值为strtolower( _CHARSET ),这样做本来在绝大多数邮件系统中均不会出现乱码,但在XoopsMailer类的sendMail方法(xoopsmailer.php中378行)却重新指定了字符集和文本编码方式:

$this->multimailer->CharSet = $this->charSet;
        $this->multimailer->Encoding = $this->encoding;

这样导致前面在构造multimailer的时候指定了字符集为XOOPS系统字符集strtolower( _CHARSET )(utf-8或者gb2312),到sendMail方法中却换成了XoopsMailer的成员charSet的值,而XoopsMailer的构造函数并没有让charSet随系统变化,而是取默认值:iso-8859-1。邮件客户端收到邮件按照iso-8859-1来显示邮件内容当然会乱码。所以我们只要正确的给XoopsMailer类实体赋给正确字符集(_CHARSET)即可。

解决办法是:

打开htdocs\class\xoopsmailer. ,137行附近
$this->multimailer = new XoopsMultiMailer();
$this->reset();
后面添加一行:
$this->charSet = strtolower( _CHARSET );
$this->encoding = ‘base64′;

更完美的解决办法是:

打开htdocs\language\schinese\xoopsmailerlocal.php和htdocs\language\schinese_utf8\xoopsmailerlocal.php 修改为:
<?php
class XoopsMailerLocal extends XoopsMailer {

    function XoopsMailerLocal(){
        $this->XoopsMailer();
        $this->charSet = strtolower( _CHARSET );
        $this->encoding = ‘base64′;
    }
}
?>

实则是xoops 中文版bug。

另外,为什么要指定encoding呢,这里涉及到email的原理,email产生的年代用7bit就足够表示所有ASCII字符可打印字符了,email发展到全世界之后,多字节语种的需要,需要使用8bit或者16bit或者更多bit来表示一个完整的字,但老式的网络设备和一些邮件系统并不能很好的处理不是7bit的内容或者并不能很好处理多字节的文本内容,这样就需要将文本做一个编码,base64和quoted-printable便是email中用来解决这个问题的最流行方法。email中附件都是用base64来编码具体内容的,用base64编码之后的邮件除非文本内容和指定字符集不一致或者本身就是乱码,否则不会出现乱码的。

当时给ceiea做Windows下邮件系统时候对email做了全面的分析,还是有些用处的。

[tags]PHPMailer,中文,邮件,XOOPS[/tags]

八月
1

[Hack]将artile模组中的文章的关键词加入到HTML的Meta头中

Author Dominic    Category XOOPS     Tags , , ,

HTML页面的keywords Meta是非常重要的一个Meta,它提供给搜索引擎以指引,告诉当前页面的主要内容,虽然目前很多搜索引擎均不在把把keywords作为唯一标示,但其重要性还是显著的。XOOPS中可以在后台设置Meta Keywords,通过Smarty变量xoops_meta_keywords写入HTML页面,但这种方式导致所有页面的这个Meta头都一样,影响了keywords Meta的效果,修改article模组的view..php文件和主题模板文件即可达到即兼顾系统设置和页面个性化keywords Meta的目的,我们将发布文章的录入的tag显示在HTML Meta头中。

首先修改htdocs\modules\article\view.article.php文件289行附近,

将原来的

if(@include_once _ROOT_PATH.”/modules/tag/include/tagbar.”){
    $xoopsTpl->assign(‘tagbar’, tagBar($article_obj->getVar(“art_keywords”, “n”)));
}

修改成:

$extra_meta_keywords = $article_obj->getVar(“art_keywords”, “n”);//Modifyed By XuYong 添加tag到html的meta标签
if(@include_once XOOPS_ROOT_PATH.”/modules/tag/include/tagbar.php”){
    $xoopsTpl->assign(‘tagbar’, tagBar($article_obj->getVar(“art_keywords”, “n”)));
    if(!empty($extra_meta_keywords))$extra_meta_keywords = str_replace(tag_get_delimiter(), “,”, $extra_meta_keywords);//Modifyed By XuYong 添加tag到html的meta标签
}
$xoopsTpl -> assign(“extra_meta_keywords”,$extra_meta_keywords);//Modifyed By XuYong 添加tag到html的meta标签

 即通过增加extra_meta_keywords Smarty变量达到个性化keywords Meta 的目的。

再修改站点所用到的主题模板文件theme.html,将原来的

<meta name=”keywords” content=”<{$xoops_meta_keywords}>” />

 修改成

<meta name=”keywords” content=”<{$extra_meta_keywords}>,<{$xoops_meta_keywords}>” />

八月
1

[Hack]让article模组显示的文章打印功能和RSS输出功能使用站点Logo

Author Dominic    Category XOOPS     Tags , ,

article模组中显示的文章的时候下面的工具箱中的打印功能输出页面头部会打印个图片,而这个图片却是article模组xoops_version.php中配置的模块图片,打印出来实在是有些刺眼,RSS输出的地方也是这样。还是改成站点的Logo图片比较好

首先修改htdocs\modules\\print.php文件90行处,

将原来的

$print_data["image"] = _URL . “/modules/” . $xoopsModule->getVar(“dirname”) . “/” . $xoopsModule->getInfo( ‘image’ );

 修改成:

$print_data["image"] = XOOPS_URL . “/images/logo.jpg”;//Modified By XuYong 采用站点Logo

再修改htdocs\modules\article\xml. 284行附近,

将原来的

“url”            => XOOPS_URL.”/modules/”.$GLOBALS["artdirname"].”/”.$xoopsModule->getInfo(“image”),

修改成:

“url”            => XOOPS_URL.”/images/logo.jpg”,

其中Logo的具体路径要根据实际情况调整。

八月
1

[Hack]解决article模组中添加文章时使用html标签导致段落换行不正确的问题

Author Dominic    Category XOOPS     Tags , ,

article模组发布文章是在编辑器下面有几个选项:“使用HTML标签”、“使用表情图”、“启用Xoops内置码”、“启用换行符(如果启用HTML标签,建议关闭) ”,一般都是选中状态(可能有配置项,但是好像默认是都选中),不明白的是为什么里面都提示“如果启用HTML标签,建议关闭”了就是不把第一个和第四个做成反选(加个Javascript控制一下就可以了),直接导致发布文章之后文章显示会换行2次,在HTML源代码中可以看到在行跟行之间出现了<BR><BR>2次,导致行与行之间多出一个br。

解决办法:编辑htdocs\modules\\edit..php文件111行,

将原来的

$dobr = $article_obj->isNew() || $newpage;

改成:

//Modified By XuYong 根据 $dohtml 调整$dobr默认值
if($dohtml==0)
{
    $dobr = $article_obj->isNew() || $newpage;
}
else
{
    $dobr = 0;
}

 这样设置了“使用HTML标签”就会自动关闭“启用换行符”了。

八月
1

突发奇想,找找2000年开办的第一个网站信息

Author Dominic    Category 生活叫吠     Tags

2000年9月份在glzhao(我的下铺兄弟,非常好的云南小伙,不知道是不是还那么瘦)的引诱下开始使用非常传统的frontpage 98制作了个人网站,全html的(邮箱空间只支持html),当时部署在学校个人邮箱内,网站名称叫做“韬光轩”,网址http://mail.ustc.edu.cn/~yxu33,还做个几个非常丑陋的GIF。网站定位也比较明确:个人记录、常用网址、常用软件下载、教程收集、个人作品。可惜后来没有坚持下去,可能受空间和金钱的影响。

目前从google中还能找到这么几条记录:
其它考研网站 http://mail.ustc.edu.cn/~yxu33/about/kaoyan.htm
[原创]一个所有关于体育的网站集合. http://mail.ustc.edu.cn/~yxu33/files/wangzhi/ball.htm (当时中文体育网站少呀)
WebMaster精华区文章阅读 http://bbs.ustc.edu.cn/cgi/bbsanc?path=/groups/GROUP_4/WebMaster/D4AF2B717/D5147038B/M.831298064.A

http://202.38.64.10/~yxu33/files/wangzhi/free_homepage.htm

发现几个历史:

  • 我做过Flash和电子贺卡
  • 我做过虚拟现实VRML
  • 我做过电子杂志
  • 我曾经对JavaScript非常感兴趣
  • 2000年我就开始弄ASP了
  • 2001年我就开始弄PHP了
  • 2000年网站叫竹叶

现在站点是不能访问的了,只能找到2001年5月份的截图:

配色实在太丑(唉,目前配色也不咋地),当时是怎么做到的不记得了,发布40天,访问量过1000。怀念当年用软盘在寝室和机房之间同步网站的时光。

七月
27

linux下常用查看Apache状态语句

Author Dominic    Category Web应用     Tags

收集linux下查看常用apache状态语句:

1、查看Apache的并发请求数及其TCP连接状态:

netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

返回结果一般如下:

SYN_RECV 28
CLOSE_WAIT 1
TIME_WAIT 9
ESTABLISHED 4
LAST_ACK 1
FIN_WAIT1 1

这里SYN_RECV表示正在等待处理的请求数;ESTABLISHED表示正常数据传输状态;TIME_WAIT表示处理完毕,等待超时结束的请求数。

2、查看apache运行进程数(prefork模式)

ps -ef | grep 2 | wc -l

返回的数字就是apache进程数,如果系统中apache文件名是httpd则执行

ps -ef | grep httpd | wc -l

(待续)

七月
27

配置Apache2启用mod_expires模块给文件添加Expires头

Author Dominic    Category Web应用     Tags , ,

使用YSlow发现所在服务器上传输出来的文件Expires头都置为Expires: Thu, 19 Nov 1981 08:52:00 GMT了,非常奇怪的一个时间(莫非apache或者php某个开发人员是这个时候出生的),YSlow给出了加载expires模块的建议。

加载expires模块之后,编辑httpd.conf加入如下配置:

# enable expirations
ExpiresActive On
# expire GIF images after a day from the time they were accessed
ExpiresByType image/gif image/jpg A86400
# HTML documents are good for a hour from the  the time they were accessed
ExpiresByType text/html M3600
# expire all default from the time they were accessed
ExpiresDefault “A7200″

七月
27

配置Apache2启用deflate压缩加快传输

Author Dominic    Category Web应用     Tags ,

今天下载了Yahoo的给Firefox开发的YSlow插件,这个插件确实不错,能够给出不少优化建议,发现所在主机没有开启deflate压缩。

首先加载mod_

在httpd.conf中加入

<Location />

# Insert filter
SetOutputFilter DEFLATE

# Netscape 4.x has some problems…
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# NOTE: Due to a bug in mod_setenvif up to 2.0.48
# the above regex won’t work. You can use the following
# workaround to get the desired effect:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# Don’t compress images
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|exe|bmp|mp3|rar|zip|swf|cab|t?gz|bz2|sit)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary

# Make sure proxies don’t deliver the wrong content
Header append Vary User-Agent env=!dont-vary

</Location>

再重启apache即可,/etc/init.d/apache2 restart

经过port80software的在线检测,首页大小从91977 bytes压缩到13376 bytes,传输速度提高6.8X,传输速度从原来12.832 s缩减到1.866 s。

如果修改配置之后提示“Invalid command ‘Header’, perhaps mis-spelled or defined by a module not included in the server configuration”,则加载Header模块即可,不过最好还是在编译apache模块时直接加上–enable-deflate –enable-headers就省事多了。

七月
26

[Hack]让Article模组子分类的文章可以加入到上级分类的专题中

Author Dominic    Category XOOPS     Tags , ,

当在article的某个分类添加了一个专题之后,目前的限制了将该分类下级分类的文章添加到这个专题中,这点限制在我看来不是很合理,作为拥有下级分类的分类,从隶属关系上讲下级分类的文章也应当属于该分类的,而且作为拥有下级分类的文章,这个分类所直接隶属的文章应当非常少,只有放到其下所有分类都不合适的时候,才放入该分类中。

修改htdocs\modules\\cp..php文件212行附近,

原来为:

    unset($subCategories_obj);
    if(!empty($category_id)){
        $criteria = new CriteriaCompo(new Criteria("top_expire", time(), ">"));
        $topics_obj =& $topic_handler->getByCategory($category_id, $xoopsModuleConfig["topics_max"], 0, $criteria, array("top_title"));
        if(count($topics_obj)>0) foreach($topics_obj as $id=>$topic){
            $topics[] = array(

修改为:

    unset($subCategories_obj);
    if(!empty($category_id)){
        $criteria = new CriteriaCompo(new Criteria("top_expire", time(), ">"));
        // by XuYong 子分类的文章可以加入到上级分类的专题中
        $category_pid= 0;
        if(!empty($category_id))$category_pid = $category_obj->getVar("cat_pid");
        //        $topics_obj =& $topic_handler->getByCategory($category_id, $xoopsModuleConfig["topics_max"], 0, $criteria, array("top_title"));
                $topics_obj =& $topic_handler->getByCategory($category_pid, $xoopsModuleConfig["topics_max"], 0, $criteria, array("top_title"));
        //End Hack
        if(count($topics_obj)>0) foreach($topics_obj as $id=>$topic){
            $topics[] = array(
七月
26

[Hack]更改article模组输出feed时时间不对的缺陷

Author Dominic    Category XOOPS     Tags , , , ,

服务时区设置为+8,在命令行行下显示正常,XOOPS中设置服务器所在时区为+0800,可article输出的feed时时间却怎么也不对,导致outlookRSS订阅中显示的文章时间也不对均为GMT+1600,哪有这样的时区哦,时区范围GMT-1200~GMT+1200。

修改方法如下:

1、修改htdocs\modules\\class\feedcreator.class.php文件中739行附近FeedDate类的构造函数FeedDate如下:

   1: function FeedDate($dateString="") {
   2:     $tzOffset = 0;
   3:     if ($dateString=="") $dateString = date("r");
   4:  
   5:     //if (is_integer($dateString)) {
   6:     if (is_numeric($dateString)) {
   7:         $this->unix = $dateString;
   8:         return;
   9:     }
  10:    // By XuYong 调整日期格式
  11:     if (preg_match("~(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s+)?(\\d{1,2})\\s+([a-zA-Z]{3})\\s+(\\d{4})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\s+(.*)~",$dateString,$matches)) {
  12:         $months = Array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12);
  13:         $this->unix = gmmktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);
  14:         if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
  15:             $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
  16:         } else {
  17:             if (strlen($matches[7])==1) {
  18:                 $oneHour = 3600;
  19:                 $ord = ord($matches[7]);
  20:                 if ($ord < ord("M")) {
  21:                     $tzOffset = (ord("A") - $ord - 1) * $oneHour;
  22:                 } elseif ($ord >= ord("M") AND $matches[7]!="Z") {
  23:                     $tzOffset = ($ord - ord("M")) * $oneHour;
  24:                 } elseif ($matches[7]=="Z") {
  25:                     $tzOffset = 0;
  26:                 }
  27:             }
  28:             switch ($matches[7]) {
  29:                 case "UT":
  30:                 case "GMT":    $tzOffset = 0;
  31:             }
  32:         }
  33:
  34:         $tzOffset += date("Z",0);
  35:         $this->unix += $tzOffset;
  36:  
  37:         if (TIME_ZONE!="")
  38:         {
  39:             $server_TZ = abs(intval($GLOBALS['xoopsConfig']['server_TZ'] * 3600.0));
  40:             $this->unix += ($server_TZ - date("Z", 0)) % 43200;
  41:         }
  42:  
  43:         return;
  44:     }
  45:     if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {
  46:         $this->unix = gmmktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
  47:         if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
  48:             $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
  49:         } else {
  50:             if ($matches[7]=="Z") {
  51:                 $tzOffset = 0;
  52:             }
  53:         }
  54:         $tzOffset += date("Z",0);
  55:         $this->unix += $tzOffset;
  56:  
  57:         if (TIME_ZONE!="")
  58:         {
  59:             $server_TZ = abs(intval($GLOBALS['xoopsConfig']['server_TZ'] * 3600.0));
  60:             $this->unix += ($server_TZ - date("Z", 0)) % 43200;
  61:         }
  62:         return;
  63:     }
  64:     $this->unix = 0;
  65: }

2、修改htdocs\modules\article\class\xml.php文件58行,

原来为:

$TIME_ZONE = $prefix.date(“H:i”, $server_TZ);

修改为:

$TIME_ZONE = $prefix.date(“H:i”, ($server_TZ – date(“Z”, 0)) % 43200); //Hack By XuYong 调整时区显示,防止出现+1600时区

专题推荐

标签

分类目录

新浪微博

存档

近期文章

近期评论

友情链接

分享按钮