推荐应用

Discuz多国语言翻译

Discuz多国语言翻译

文库系统/文档系统

文库系统/文档系统

美食菜谱发布菜谱

美食菜谱发布菜谱

漫画阅读中心

漫画阅读中心

小说阅读中心

小说阅读中心

语言包切换基本文件

语言包切换基本文件

成语闯关

成语闯关

谷歌登錄Google登錄

谷歌登錄Google登錄

轻APP

轻APP

网上祭祀祭拜扫墓

网上祭祀祭拜扫墓

手机MP4视频上传

手机MP4视频上传

彩票开奖号码公布

彩票开奖号码公布

DZX泰语/傣语

DZX泰语/傣语

DZX日文版(日本语)

DZX日文版(日本语)

后台的邮件通知更新天数功能分析

发布于 2012-12-24
邮件通知更新天数功能介绍:当用户多少天没有登录站点的时候才会给其发送邮件通知。

邮件通知更新天数的位置:后台-》全局-》空间设置-》基本设置下的邮件通知更新天数,如图。
设置为0则不启用该功能,单位为天。

功能分析:
比如用户A回复了用户B的帖子,这时候在用户A回复用户B帖子的同时会执行下面这个操作。
具体文件:sourceincludepostpost_newreply.php的98行附近。notification_add($post['authorid'], 'pcomment', 'comment_add', array(
      'tid' => $_G['tid'],
      'pid' => $_G['gp_pid'],
      'subject' => $thread['subject'],
      'commentmsg' => cutstr(str_replace(array('', '', ''), '', preg_replace("/\[color=([#\w]+?)\]/i", "", stripslashes($comment))), 200)
    ));
notification_add()函数是在source/function/function_core.php文件定义的,1897行附近,具体代码如下:function notification_add($touid, $type, $note, $notevars = array(), $system = 0) {
  global $_G;
  $tospace = array('uid'=>$touid);
  space_merge($tospace, 'field_home');
  $filter = empty($tospace['privacy']['filter_note'])?array():array_keys($tospace['privacy']['filter_note']);
  if($filter && (in_array($type.'|0', $filter) || in_array($type.'|'.$_G['uid'], $filter))) {
    return false;
  }
  $notevars['actor'] = "".$_G['member']['username']."";
  if(!is_numeric($type)) {
    $vars = explode(':', $note);
    if(count($vars) == 2) {
      $notestring = lang('plugin/'.$vars[0], $vars[1], $notevars);
    } else {
      $notestring = lang('notification', $note, $notevars);
    }
    $frommyapp = false;
  } else {
    $frommyapp = true;
    $notestring = $note;
  }
  $oldnote = array();
  if($notevars['from_id'] && $notevars['from_idtype']) {
    $oldnote = DB::fetch_first("SELECT * FROM ".DB::table('home_notification')."
      WHERE uid='$touid' AND from_id='$notevars[from_id]' AND from_idtype='$notevars[from_idtype]'");
  }
  if(empty($oldnote['from_num'])) $oldnote['from_num'] = 0;
  $notevars['from_num'] = $notevars['from_num'] ? $notevars['from_num'] : 1;
  $setarr = array(
    'uid' => $touid,
    'type' => $type,
    'new' => 1,
    'authorid' => $_G['uid'],
    'author' => $_G['username'],
    'note' => addslashes($notestring),
    'dateline' => $_G['timestamp'],
    'from_id' => $notevars['from_id'],
    'from_idtype' => $notevars['from_idtype'],
    'from_num' => ($oldnote['from_num']+$notevars['from_num'])
  );
  if($system) {
    $setarr['authorid'] = 0;
    $setarr['author'] = '';
  }
  if($oldnote['id']) {
    DB::update('home_notification', $setarr, array('id'=>$oldnote['id']));
  } else {
    $oldnote['new'] = 0;
    DB::insert('home_notification', $setarr);
  }
  if(empty($oldnote['new'])) {
    DB::query("UPDATE ".DB::table('common_member')." SET newprompt=newprompt+1 WHERE uid='$touid'");
    require_once libfile('function/mail');
    $mail_subject = lang('notification', 'mail_to_user');
    sendmail_touser($touid, $mail_subject, $notestring, $frommyapp ? 'myapp' : $type);
  }
  if(!$system && $_G['uid'] && $touid != $_G['uid']) {
    DB::query("UPDATE ".DB::table('home_friend')." SET num=num+1 WHERE uid='$_G[uid]' AND fuid='$touid'");
  }
}
前面都是给相应用户发送提醒操作,具体不再此处进行分析,单独看发送邮件代码,如下:require_once libfile('function/mail');
    $mail_subject = lang('notification', 'mail_to_user');
    sendmail_touser($touid, $mail_subject, $notestring, $frommyapp ? 'myapp' : $type);
这里会执行sendmail_touser()函数,$mail_subject是邮件标题,$notestring是提醒的内容,$frommyapp是操作的类型。
sendmail_touser()函数是在source\function\function_mail.php文件里定义的,204行附近,具体代码如下:function sendmail_touser($touid, $subject, $message, $mailtype='') {
  global $_G;
  if(empty($_G['setting']['sendmailday'])) return false;
  require_once libfile('function/home');
  $tospace = getspace($touid);
  if(empty($tospace['email'])) return false;
  space_merge($tospace, 'field_home');
  space_merge($tospace, 'status');
  $acceptemail = $tospace['acceptemail'];
  if(!empty($acceptemail[$mailtype]) && $_G['timestamp'] - $tospace['lastvisit'] > $_G['setting']['sendmailday']*86400) {
    if(empty($tospace['lastsendmail'])) {
      $tospace['lastsendmail'] = $_G['timestamp'];
    }
    $sendtime = $tospace['lastsendmail'] + $acceptemail['frequency'];
    $query = DB::query("SELECT * FROM ".DB::table('common_mailcron')." WHERE touid='$touid' LIMIT 1");
    if($value = DB::fetch($query)) {
      $cid = $value['cid'];
      if($value['sendtime'] < $sendtime) $sendtime = $value['sendtime'];
      DB::update('common_mailcron', array('email'=>addslashes($tospace['email']), 'sendtime'=>$sendtime), array('cid'=>$cid));
    } else {
      $cid = DB::insert('common_mailcron', array('touid'=>$touid, 'email'=>addslashes($tospace['email']), 'sendtime'=>$sendtime), 1);
    }
    $message = preg_replace("/href\=\"(?!http\:\/\/)(.+?)\"/i", 'href="'.$_G['siteurl'].'\\1"', $message);
    $setarr = array(
      'cid' => $cid,
      'subject' => addslashes($subject),
      'message' => addslashes($message),
      'dateline' => $_G['timestamp']
    );
    DB::insert('common_mailqueue', $setarr);
    return true;
  }
  return false;
}
下面具体分析代码的执行过程:if(empty($_G['setting']['sendmailday'])) return false;首先会判断$_G['setting']['sendmailday']变量是否存在,如果不存在则直接返回false。$_G['setting']['sendmailday']就是后台设置的邮件通知更新天数。require_once libfile('function/home');
  $tospace = getspace($touid);
  if(empty($tospace['email'])) return false;
getspace($touid)是要获取发送对象的详细信息,如果该用户没有设置邮箱,就直接返回false。space_merge($tospace, 'field_home');
  space_merge($tospace, 'status');
  $acceptemail = $tospace['acceptemail'];
前两句是查询该用户的相关信息。
$tospace['acceptemail']是该用户设置的邮件提醒。邮件提醒设置的具体位置在家园的设置-》邮件提醒。if(!empty($acceptemail[$mailtype]) && $_G['timestamp'] - $tospace['lastvisit'] > $_G['setting']['sendmailday']*86400) {首先判断该类型的操作是否进行邮件提醒(判断$acceptemail[$mailtype]变量是否存在),同时判断当前时间(TIMESTAMP)- 用户上一次的活动时间($tospace['lastvisit']) > 后台设置的邮件通知更新天数($_G['setting']['sendmailday'])*86400。不满足则跳出if判断,返回false。if(empty($tospace['lastsendmail'])) {
$tospace['lastsendmail'] = $_G['timestamp'];
}
如果用户上一次发送邮件的时间不存在,那么就赋予当前时间给$tospace['lastsendmail']。$sendtime = $tospace['lastsendmail'] + $acceptemail['frequency'];计算发送邮件的时间,$acceptemail['frequency']为邮件提醒里的发送频率设置。$query = DB::query("SELECT * FROM ".DB::table('common_mailcron')." WHERE touid='$touid' LIMIT 1");
    if($value = DB::fetch($query)) {
      $cid = $value['cid'];
      if($value['sendtime'] < $sendtime) $sendtime = $value['sendtime'];
      DB::update('common_mailcron', array('email'=>addslashes($tospace['email']), 'sendtime'=>$sendtime), array('cid'=>$cid));
    } else {
      $cid = DB::insert('common_mailcron', array('touid'=>$touid, 'email'=>addslashes($tospace['email']), 'sendtime'=>$sendtime), 1);
    }
首先到common_mailcron表里查询是否有向该用户发送邮件的邮件任务。如果存在就更新任务,如果不存在就往表里新插入一条任务。$message = preg_replace("/href\=\"(?!http\:\/\/)(.+?)\"/i", 'href="'.$_G['siteurl'].'\\1"', $message);
    $setarr = array(
      'cid' => $cid,
      'subject' => addslashes($subject),
      'message' => addslashes($message),
      'dateline' => $_G['timestamp']
    );
    DB::insert('common_mailqueue', $setarr);
    return true;
前面是对内容进行处理,然后往common_mailqueue表里插入一条数据,返回true。
至此,相应的邮件任务已经添加,但是邮件还没有发送。下面看下邮件任务是如何触发处理的。
在template\default\common\footer.htm文件,79行附近,找到如下代码。
  
  
如果不存在$_G['cookie']['sendmail'],那么就会输出一个js。
看js的src地址,是进入到了source\include\misc\misc_sendmail.php文件中,下面只分析重点,其他不做分析。$query = DB::query("SELECT * FROM ".DB::table('common_mailcron')." WHERE sendtime<='$_G[timestamp]' ORDER BY sendtime LIMIT 0,$pernum");
while ($value = DB::fetch($query)) {
  if($value['touid']) $touids[$value['touid']] = $value['touid'];
  $cids[] = $value['cid'];
  $list[$value['cid']] = $value;
}
if(empty($cids)) exit();
$query = DB::query("SELECT * FROM ".DB::table('common_mailqueue')." WHERE cid IN (".dimplode($cids).")");
while ($value = DB::fetch($query)) {
  $sublist[$value['cid']][] = $value;
}
从common_mailcron和common_mailqueue表分别查询数据然后赋值。if($touids) {
  DB::query("UPDATE ".DB::table('common_member_status')." SET lastsendmail='$_G[timestamp]' WHERE uid IN (".dimplode($touids).")");
}
更新common_member_status表里用户的最后发送邮件时间。DB::query("DELETE FROM ".DB::table('common_mailcron')." WHERE cid IN (".dimplode($cids).")");
DB::query("DELETE FROM ".DB::table('common_mailqueue')." WHERE cid IN (".dimplode($cids).")");
删除common_mailcron表里跟common_mailqueue表里删除相应的任务require_once libfile('function/mail');
foreach ($list as $cid => $value) {
  $mlist = $sublist[$cid];
  if($value['email'] && $mlist) {
    $subject = getstr($mlist[0]['subject'], 80, 0, 0, 0, -1);
    $message = '';
    foreach ($mlist as $subvalue) {
      if($subvalue['message']) {
        $message .= "
$subvalue[subject]
$subvalue[message]
";
      } else {
        $message .= $subvalue['subject'].'
';
      }
    }
    if(!sendmail($value['email'], $subject, $message)) {
      runlog('sendmail', "$value[email] sendmail failed.");
    }
  }
}
执行相应的发送邮件操作。
至此邮件就发送出去了。
扫一扫添加有偿QQ
扫一扫添加微信客服