现在的位置: 首页 > 综合 > 正文

php脚本(功能发邮件;技术mongodb队列,锁文件。linux运行)

2013年03月08日 ⁄ 综合 ⁄ 共 14181字 ⁄ 字号 评论关闭

主文件:MongoMailSend.php

包含文件:include.php

配置文件:config.php

自定义类库目录:library

 

目录结构:

主文件:scripts/MongoMailSend.php

包含文件:scripts/include.php

配置文件:scripts/config.php

自定义类库目录:

scripts/library

scripts/library/Hrs

scripts/library/Hrs/Mongo

数据库

mongodb数据库连接:scripts/library/Hrs/Mongo/Config.php

mongodb数据库邮件表的操纵(要继承与Table.php文件的):scripts/library/Hrs/Mongo/QueueMail.php

mongodb数据库操纵的类文件:scripts/library/Hrs/Mongo/Table.php

邮件

scripts/library/Hrs/Mail

发短信的类文件:scripts/library/Hrs/Mail/Sender.php

 

MongoMailSend.php

<?php
/*
 * 从mongodb数据库读取邮件信息数据, 调用邮件发送接口发送邮件
 * 具体实现文件
 */
//加载include.php文件,包括文件,这样就能加载所有的文件了。include.php文件还包含一些方法,如锁文件的创建与删除
include_once 'include.php';
//设置锁文件,根据自己情况来,也可以不用锁的。get_temp_dir()方法在include.php文件中
//创建锁文件
//程序跑完再解锁,没跑完如果运行时间超过1800s,则重新上锁。
//没解锁,这个文件不能重复运行。
$lock_file = get_temp_dir().'/mongomailsend.lock';
//文件上锁
//lock_up($lock_file);

//以smtp方式发送邮件,Zend_Mail_Transport_Smtp对象需要在send()方法被调用之前创建并注册到Zend_Mail中去。(!!!!!!)
//创建Zend_Mail_Transport_Smtp对象$smtp_tp
$smtp_tp = new Zend_Mail_Transport_Smtp($config['mail']['host'],$config['mail']['smtp']);
//把$smtp_tp注册到Zend_Mail中
Zend_Mail::setDefaultTransport($smtp_tp);
//把发送者邮箱与发送者名字也注册到Zend_Mail中
Zend_Mail::setDefaultFrom($config['mail']['from'],$config['mail']['fromname']);

//mongodb数据库配置信息
$server = array('host'=>$config['databases']['mongodb']['host'],
			'port'=>$config['databases']['mongodb']['port'],
        	'database'=>$config['databases']['mongodb']['database']);
//设置mongodb配置文件中的配置信息,要识别Hrs_Mongo_Config类文件,需要include.php写一个自动加载类方法 
Hrs_Mongo_Config::set($server);
//new 邮件队列的对象
$queue = new Hrs_Mongo_QueueMail();
//是否开启密抄
$open_bcc = $config['mail']['open_bcc'];
//发送失败的数目,默认为0,失败时自增加1。
$send_status = 0;
//当前时间
$nowtime = time();


//测试数据
/*
$arr = array(
        'email'=>'xxx@163.com',
        'subject'=>'mongo测试',
        'content'=>'内容区域',
        'attachments'=>'',
        'status'=>0,
        'fail_times'=>0,
        'create_time'=>$nowtime,
        'sent_time'=>0,
        'mailfrom'=>'xxx@126.com',
        'fromname'=>'xxx',
        'replyto'=>'');
$queue->insert($arr);
*/
//获取需要发送的队列信息
$result = $queue->getQueueMail();
/*
 *判断队列信息是否为空
 *队列存在的话,是数组,foreach循环一下数组。
 *send_mail()发邮件的函数 ,成功与否都返回一个状态值$status 	
 *$status true时发送成功
 *$status不为true时,$send_status自增加1这个记录发送失败的数目
 *注意!发送时有一个参数判断是否密抄的 $open_bcc
 *send_mail()参数讲解
 *mail 接收者邮箱
 *toname
 *subject邮件主题
 *content邮件内容
 *attachments附件
 *mailfrom发件者邮箱
 *fromname发件者名称
 *replyto回复地址(可为空)
 *open_bcc是否密抄,用于系统监控
 */
if (!empty($result)) {
    foreach($result as $row){
    	//如果数据库有发件人邮箱就用这个邮箱,没有就用配置文件默认的邮箱
    	//如果数据库有发件人名字就用这个名字,没有就用配置文件默认的名字
    	$mailfrom = $row['mailfrom'] ? $row['mailfrom'] : $config['mail']['mailfrom'];
    	$fromname = $row['fromname'] ? $row['fromname'] : $config['mail']['fromname'];
        $status = send_mail($row['email'], $row['toname'], $row['subject'], $row['content'], $row['attachments'], $mailfrom, $fromname, $row['replyto'], $open_bcc);
        if($status == true){
            $queue->changeMail(array('$set'=>array('status'=>1, 'sent_time'=>$nowtime)), $row['_id']);
        }else{
            $send_status += 1;
            $queue->changeMail(array('$set'=>array('status'=>2,'sent_time'=>$nowtime),
                    '$inc'=>array('fail_times'=>1)), $row['_id']);
        }
    }
}
else {
    echo 'no mail send';
}
//判断最后发送情况
if($send_status){
	echo "mail num=".$send_status."mail send fail\n";
}else if(!count($result)){
	echo "no mail send,".date("Y-m-d H:i:s")."\n";
}else{
	echo "mail send success\n";
}
//文件解锁
//un_lock($lock_file);


include.php

<?php
/*
 * 包括文件:包括的如下
 * 数据库配置文件——》config.php
 * 自定义类库目录——》library目录
 */
//设置时区,亚洲上海
date_default_timezone_set('Asia/Shanghai');
/*
 *加载config.php数据库配置文件
 *__FILE__当前文件的路径
 *dirname()返回路径中的目录部分
 *dirname(__FILE__),返回当前文件的目录
 */
include_once(dirname(__FILE__).'/config.php');
/*
 * 加载自定义类库(这里不同于Zend Framework)
 * 动态设置环境变量,把自定义类库放置到环境变量中
 * SCRIPT_PATH脚本路径
 * set_include_path动态设置环境变量	PATH_SEPARATOR路径分离器,我们的环境变量中的 ';'
 * realpath()返回绝对路径	注意,你必须有,否则返回空
 * get_include_path获取环境变量	
 */
defined('SCRIPT_PATH')||define('SCRIPT_PATH', dirname(__FILE__));
set_include_path(implode(PATH_SEPARATOR, array(
	realpath(SCRIPT_PATH.'/library'),
	get_include_path()
)));

/*
 * 文件上锁,锁文件主要也就是时间锁的问题。这里半个小时1800s
 * file_exists()判断文件是否存在
 * file_get_contents()获取文件的内容
 * 只要时间不超过1800s,文件就处于锁定状态
 * 超过1800s,重新写锁文件的内容
 * 也就是说1800s,运行时间,或者解锁。
 */
function lock_up($file, $time=1800)
{
	if(file_exists($file)){
		$content = file_get_contents($file);
		if((intval(time())-intval($content)) > $time){
			file_put_contents($file, time());
		}else{
			die('file is locked!');
		}
	}else{
		file_put_contents($file, time());
	}
}

/*
 * 文件解锁,删除目录
 * unlink();
 */
function un_lock($file)
{
	@unlink($file);
}

/*
 * 临时目录,存放脚本锁文件位置
 * strncmp()比较两个字符串	WIN下就存放在  C:\WINDOWS\TEMP
 * getenv()系统的环境变量
 */
function get_temp_dir()
{	
	if(strncmp(PHP_OS, 'WIN', 3)===0){
		return getenv('TEMP');
	}else{
		return '/tmp';
	}
}

/*
 * 格式化邮件
 * 处理附近问题
 * @param string $att
 */
function attaformat($att){
    /*
     * 当存在附件时,无论一个附件或N个附件都要以数组的形式再进行序列化.直接对单一附件进行序列化将导致反序列化后发送邮件的错误
     * example:
     *     文件一=array('filename','mimeType','disposition','encoding');
     * right: serialize(array('文件1'));
     * error: serialize('文件1');
     */
    $attArr = "";

    $attArr = unserialize($att);

    return is_array($attArr) ? $attArr : '';
}

/*
 * 发送邮件
 * @param string $tomail      #收信人邮件
 * @param string $toName      #收信人名称
 * @param string $subject     #邮件标题
 * @param string $bodyText    #邮件内容
 * @param string $attachments #邮件附件
 * @param string $mailfrom    #发送人邮件
 * @param string $fromname    #发送人名称
 * @param string $replyto     #回复邮件地址
 * @param string $open_bcc    #是否打开密送
 * @return boolean
 */
function send_mail($tomail,$toName,$subject,$bodyText,$attachments=NULL,$mailfrom="",$fromname="",$replyto="", $open_bcc=false){
    global $config;
    $bcc_mail = $config['mail']['bcc_mail'];
    $attachment = attaformat($attachments);
    $status = true;
    try{
        $email = new Hrs_Mail_Sender('UTF-8');
        $email->setHeaderEncoding(Zend_Mime::ENCODING_BASE64);
        if($mailfrom)
            $email->setFrom($mailfrom, $fromname);
        if($replyto)
            $email->setReplyTo($replyto, $fromname);
        //是否密抄(系统监控用)
        if($open_bcc && $bcc_mail)
            $email->addBcc($bcc_mail);

        $email->addTo($tomail,$toName)
        ->setSubject(html_entity_decode($subject, 2, 'UTF-8'))
        ->setBodyHtml($bodyText);
        if($attachment){
            $attaNum = count($attachment);
            for($j=0;$j<$attaNum;$j++){
                if(!isset($attachment[$j]['body'])) {
                    echo "可能有一个以上附件格式不正确被抛弃。\n";
                    continue;
                }
                $email->createAttachment(
                        $attachment[$j]['body'],
                        $attachment[$j]['mimeType'],
                        $attachment[$j]['disposition'],
                        $attachment[$j]['encoding'],
                        $attachment[$j]['filename']);     //默认二进制文件 base64编码传输
            }
        }
        $email->send();
        echo "mail success\n\r";
    }catch (Exception $e){
        //邮件发送失败
        echo "mail fail:".$e->getMessage()."\n";
        $status = false;
    }
    unset($email);
    return $status;
}

/*
 * 自动加载类方法 	使Hrs_Mongo_Config可以识别
 * class_exists()	类是否已定义
 * interface_exists() 接口是否已定义
 * str_replace() 字符串替换函数
 * $filename文件名(不带后缀)
 * 加载类文件 require_once();
 */
function __autoload($class)
{
	if(class_exists($class, false) || interface_exists($class, false)){
		return ;
	}
	try {
		$filename = str_replace('_', '/', $class);
		@require_once ($filename.'.php');
		if(!class_exists($class, false) || !interface_exists($class, false)){
			throw new Exception('Class ' . $class . ' not found');
		}
	} catch (Exception $e) {
		return ;
	}
}

config.php

<?php
/*
 * 数据库配置文件
 * host
 * port
 */
$config['databases']['mongodb']['host'] = '172.16.26.240';
$config['databases']['mongodb']['port'] = '27088';
$config['databases']['mongodb']['database'] = 'local';

/*
 * mail smtp配置
 * mail host			发送邮件服务器
 * mail smtp port 		smtp端口号(25是smtp标准端口号)
 * mail smtp auth		login(验证用户名与口令)(login登录意思)
 * mail smtp username	用户名
 * mail smtp password	口令
 * mail from			发送者邮箱(或企业邮箱)(邮箱的后缀就是mail host)
 * mail fromname		发送者名字(或企业名字)
 * mail open_bcc		是否开启密抄 true是开启,false是关闭
 * mail bcc_mail		密抄邮箱
 * 注意!密抄功能是监控的需要。
 */
$config['mail']['host'] = '126.com';
$config['mail']['smtp']['port'] = '25';
$config['mail']['smtp']['auth'] = 'login';
$config['mail']['smtp']['username'] = 'xxxxx';
$config['mail']['smtp']['password'] = 'xxxxx';
$config['mail']['from'] = 'xxx@126.com';
$config['mail']['fromname'] = 'XXX';
$config['mail']['open_bcc'] = false;					//是否开启密抄 true是开启,false是关闭		
$config['mail']['bcc_mail'] = 'xxxxx@126.com';	//密抄邮箱


library/Hrs/Mongo/Config.php

<?php
require_once 'Zend/Exception.php';

class Hrs_Mongo_Config
{

    const VERSION = '1.7.0';
    const DEFAULT_HOST = 'localhost';
    const DEFAULT_PORT = 27017;

    private static $host = self::DEFAULT_HOST ;
    private static $port = self::DEFAULT_PORT ;
    private static $options = array(
            'connect' => true,
            'timeout' => 30,
            //'replicaSet' => '' //If this is given, the master will be determined by using the ismaster database command on the seeds
    );

    public static $conn = '';
    public static $defaultDb = '';
    public static $linkStatus = '';
    public static function set($server = 'mongodb://localhost:27017', $options = array('connect' => true)) {

        if(!$server){
            $url = 'mongodb://'.self::$host.':'.self::$port;
        }

        if(is_array($server)){
            if(isset($server['host'])){
                self::$host = $server['host'];
            }
            if(isset($server['port'])){
                self::$port = $server['port'];
            }

            if(isset($server['user']) && isset($server['pass'])){
                $url = 'mongodb://'.$server['user'].':'.$server['pass'].'@'.self::$host.':'.self::$port;
            }else{
                $url = 'mongodb://'.self::$host.':'.self::$port;
            }
        }

        if(is_array($options)){
            foreach (self::$options as $o_k=>$o_v){
                if(isset($options[$o_k]))
                    self::$options[$o_k] = $o_v;
            }
        }

        try{                        
            self::$conn = new Mongo($url, self::$options);
            self::$linkStatus = 'success';
        }catch (Exception $e){
            self::$linkStatus = 'failed';
        }

        if(isset($server['database'])){
            self::selectDB($server['database']);
        }
    }

    public static function selectDB($database){
        if($database){
            try {
                if(self::$linkStatus=='success')
                    self::$defaultDb = self::$conn->selectDB($database);
                return self::$defaultDb;
            }
            catch(InvalidArgumentException $e) {
                throw new Zend_Exception('Mongodb数据库名称不正确');
            }
        }else{
            throw new Zend_Exception('Mongodb数据库名称不能为空');
        }
    }
}

 

library/Hrs/Mongo/QueueMail.php

<?php

require_once 'Hrs/Mongo/Table.php';
/*
 mongo表结构对应mysql表结构如下:
CREATE TABLE `queue_mails` (
        `qid` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'PK',
        `email` varchar(100) NOT NULL COMMENT '邮件地址',
        `subject` varchar(255) NOT NULL COMMENT '邮件主题',
        `content` longtext NOT NULL COMMENT '邮件内容',
        `attachments` mediumblob COMMENT '邮件附件,最大16M。多个附件使用分隔符<!--attachment-->分隔。附件名称与附件内容之间用<!--separator-->分隔',
        `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '发送状态,0:未发送,1:已发送,2:发送失败',
        `fail_times` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '失败次数',
        `create_time` int(10) unsigned NOT NULL COMMENT '创建时间',
        `sent_time` int(10) unsigned NOT NULL COMMENT '发送时间',
        `mailfrom` varchar(100) NOT NULL COMMENT '发送者邮箱',
        `fromname` varchar(100) NOT NULL COMMENT '发送者名称',
        `replyto` varchar(100) NOT NULL COMMENT '发送者的接受邮箱',
        PRIMARY KEY (`qid`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='邮件队列'
*/

class Hrs_Mongo_QueueMail extends Hrs_Mongo_Table
{
    protected $_name = 'mails';
    protected $_row = array(
            'email' => '',
            'subject' => '',
            'content' => '',
            'attachments' => '',
            'status' => 0,
            'fail_times' => 0,
            'create_time' => 0,
            'sent_time' => 0,
            'mailfrom' => '',
            'fromname' => '',
            'replyto' => ''
    );

    public function addRow($data){
        $prepareData = array();
        foreach($this->_row as $key=>$val){
            if(isset($data[$key])){
                $prepareData[$key] = $data[$key];
            }else{
                $prepareData[$key] = $val;
            }
        }
        $this->insert($prepareData);

    }

    public function getQueueMail(){
        return $this->find(array('status'=>array('$in'=>array(0,2)),'fail_times'=>array('$lt'=>4)))->toArray();
    }

    public function changeMail($data, $_id){
        $result = $this->update($data, array('_id'=>new MongoId($_id)));
        return $result;
    }

    public function deleteMail($_id){
        $result = $this->delete(array('_id'=>new MongoId($_id)));
    }
}

 

library/Hrs/Mongo/Table.php

<?php

require_once 'Hrs/Mongo/Config.php';

abstract class Hrs_Mongo_Table
{
    protected $_db = '';
    protected $_name = '';
    protected $_data = array();

    protected $c_options = array(
            'fsync'=>true,
            'safe'=>true
    );
    protected $u_options = array(
    //'upsert'=>false,
            'multiple'=>true,
            'fsync'=>true,
            'safe'=>true
    );
    /*
     protected $r_options = array(

     );*/
    protected $d_options = array(
            'fsync'=>true,
            'justOne'=>false,
            'safe'=>true
    );

    protected function _setAdapter($database=''){
        if(!$database)
            throw new Zend_Exception('Mongodb数据库名称不能为空');

        Hrs_Mongo_Config::selectDB($database);
    }

    public function __construct() {

        if(Hrs_Mongo_Config::$conn instanceof Mongo){
            $name = $this->_name;
            $defDb = Hrs_Mongo_Config::$defaultDb;
            $this->_db = $defDb->$name;
        }else{
            throw new Zend_Exception('Mongodb服务器连接失败');
        }
    }

    public function insert($data){

        if(!$this->testLink()) return false;
        $ret = $this->_db->insert($data, $this->c_options);
        return $ret;
    }

    public function update($data, $where){
        if(!$this->testLink()) return false;
        return $this->_db->update($where, $data, $this->u_options);
    }

    public function find($where=array(),$limit=0){
        if($this->testLink()) {
            if($limit>0){
                $this->_data = $where ? $this->_db->find($where)->limit($limit)->snapshot() : $this->_db->find()->limit($limit)->snapshot();
            }else{
                $this->_data = $where ? $this->_db->find($where)->limit($limit)->snapshot() : $this->_db->find()->limit($limit)->snapshot();
            }
        }
        return $this;
    }

    //find cursor
    public function look($where=array(),$fields=array()){
        if($this->testLink()) {
            if($fields){
                return $where ? $this->_db->find($where,$fields): $this->_db->find()->fields($fields);
            }else{
                return $where ? $this->_db->find($where) : $this->_db->find();
            }
        }
        return false;
    }

    public function delete($where){
        if(!$this->testLink()) return false;
        return $this->_db->remove($where, $this->d_options);
    }

    public function dropMe(){
        if(!$this->testLink()) return false;
        return $this->_db->drop();
    }

    public function __toString(){
        return $this->_data;
    }

    public function toArray(){
        $tmpData = array();
        foreach($this->_data as $id=>$row){
            $one_row = array();
            foreach($row as $key=>$col){
                $one_row[$key] = $col;
            }
            $one_row['_id'] = $id;
            $tmpData[] = $one_row;
        }
        return $tmpData;
    }

    protected function testLink(){
        return Hrs_Mongo_Config::$linkStatus == 'success' ? true :false;
    }
}

 

library/Hrs/Mail/Sender.php

<?php

include_once 'Zend/Mail.php';

class Hrs_Mail_Sender extends Zend_Mail
{
    public function setSubject($subject)
    {
        if ($this->_subject === null) {
            $subject = $this->_filterOther($subject);
            $this->_subject = $this->_hrs2_encodeHeader($subject);
            $this->_storeHeader('Subject', $this->_subject);
        } else {
            /**
             * @see Zend_Mail_Exception
             */
            require_once 'Zend/Mail/Exception.php';
            throw new Zend_Mail_Exception('Subject set twice');
        }
        return $this;
    }

    private function _hrs2_encodeHeader($value){
        if (Zend_Mime::isPrintable($value) === false) {
            if ($this->getHeaderEncoding() === Zend_Mime::ENCODING_QUOTEDPRINTABLE) {
                $value = Zend_Mime::encodeQuotedPrintableHeader($value, $this->getCharset(), Zend_Mime::LINELENGTH, Zend_Mime::LINEEND);
            } else {
                $value = $this->_hrs2_encodeBase64Header($value, $this->getCharset(), Zend_Mime::LINELENGTH, Zend_Mime::LINEEND);
            }
        }
        return $value;
    }

    private function _hrs2_encodeBase64Header($value, $charset, $lineLength, $lineEnd){
        $prefix = '=?' . $charset . '?B?';
        $suffix = '?=';
        $remainingLength = $lineLength - strlen($prefix) - strlen($suffix);

        $encodedValue = $this->_hrs2_encodeBase64($value, $remainingLength, $lineEnd);
        $encodedValue = str_replace($lineEnd, $suffix . $lineEnd . ' ' . $prefix, $encodedValue);
        $encodedValue = $prefix . $encodedValue . $suffix;
        return $encodedValue;
    }

    private function _hrs2_encodeBase64($str, $lineLength, $lineEnd){
        $lineLimit    = floor($lineLength * 3 /4);
        $encoding     = mb_detect_encoding($str);
        $encodedLines = array();
        $line = 0;
        while(strlen($str)>0){
            $encodedLine    = mb_strcut($str, 0, $lineLimit, $encoding);
            $encodedLines[] = base64_encode(rtrim($encodedLine));
            $str = rtrim(mb_strcut($str.'   ', $lineLimit, strlen($str), $encoding));
            $line++;
        }
        return implode($lineEnd, $encodedLines);
    }
}

 

 

 

 

 

 

抱歉!评论已关闭.