如何将PHP提取的邮件导入WordPress自定义文章类型E-mail Inboxes
实现方案
前置注意事项
- 确认你的服务器已经开启PHP的
imap扩展,否则邮件读取代码无法运行 - 确认你创建的自定义文章类型的slug,WordPress默认会将名称
E-mail Inboxes转换为email-inboxes,如果你的实际slug不同,后续代码中对应位置需要替换为你自己的slug - 原有代码中993端口为SSL加密端口,已经对连接配置做了适配修正,避免连接失败
步骤1:编写邮件导入逻辑
修正后的邮件读取类+导入代码
你可以把下面的代码放到当前主题的functions.php文件中,或者单独打包成自定义插件使用:
class Email_reader { // imap server connection public $conn; // inbox storage and inbox message count private $inbox; private $msg_cnt; // 替换为你自己的邮箱配置 private $server = 'myserver.com'; private $user = 'myserver@mail.com'; private $pass = 'PASSWORD'; private $port = 993; // connect to the server and get the inbox emails function __construct() { $this->connect(); $this->inbox(); } // close the server connection function close() { $this->inbox = array(); $this->msg_cnt = 0; imap_close($this->conn); } // 适配993 SSL端口的连接配置 function connect() { $this->conn = imap_open('{'.$this->server.':'.$this->port.'/ssl/novalidate-cert}', $this->user, $this->pass); } // move the message to a new folder function move($msg_index, $folder='INBOX.Processed') { imap_mail_move($this->conn, $msg_index, $folder); imap_expunge($this->conn); $this->inbox(); } // get a specific message (1 = first email, 2 = second email, etc.) function get($msg_index=NULL) { if (count($this->inbox) <= 0) { return array(); } elseif ( ! is_null($msg_index) && isset($this->inbox[$msg_index])) { return $this->inbox[$msg_index]; } return $this->inbox[0]; } // read the inbox function inbox() { $this->msg_cnt = imap_num_msg($this->conn); $in = array(); for($i = 1; $i <= $this->msg_cnt; $i++) { $in[] = array( 'index' => $i, 'header' => imap_headerinfo($this->conn, $i), 'body' => imap_body($this->conn, $i), 'structure' => imap_fetchstructure($this->conn, $i) ); } $this->inbox = $in; } } // 邮件导入到自定义文章类型的核心函数 function import_emails_to_cpt() { $email_reader = new Email_reader(); $all_emails = $email_reader->inbox; if(empty($all_emails)) return; foreach($all_emails as $email) { $header = $email['header']; // 处理邮件标题编码,避免乱码 $subject = imap_utf8($header->subject); // 用邮件唯一ID做去重判断,避免重复导入 $message_id = $header->message_id; // 查询当前邮件是否已经导入过 $existing_post = get_posts(array( 'post_type' => 'email-inboxes', // 替换为你自己的自定义文章类型slug 'meta_key' => 'email_message_id', 'meta_value' => $message_id, 'posts_per_page' => 1 )); if(!empty($existing_post)) { // 已导入过的邮件移动到已处理文件夹,跳过 $email_reader->move($email['index']); continue; } // 组装WordPress文章数据 $post_data = array( 'post_title' => $subject ? $subject : '无标题邮件', 'post_content' => $email['body'], 'post_status' => 'publish', 'post_type' => 'email-inboxes', // 替换为你自己的自定义文章类型slug 'post_date' => date('Y-m-d H:i:s', strtotime($header->date)) ); // 插入文章 $post_id = wp_insert_post($post_data); if(!is_wp_error($post_id)) { // 把邮件额外信息存为自定义字段,方便后续调用 update_post_meta($post_id, 'email_message_id', $message_id); update_post_meta($post_id, 'email_from', $header->fromaddress); update_post_meta($post_id, 'email_to', $header->toaddress); update_post_meta($post_id, 'email_date', $header->date); // 导入成功后移动到已处理文件夹,避免下次重复读取 $email_reader->move($email['index']); } } $email_reader->close(); } // 临时触发代码:去掉下面一行的注释,访问一次网站前台就会执行一次导入,测试完成后记得删掉这行 // add_action('wp_footer', 'import_emails_to_cpt');
步骤2:后续优化建议
- 测试阶段先注释掉
$email_reader->move相关逻辑,确认导入的内容没有问题后再打开,避免误移动邮件 - 如果需要自动定时导入,可以借助WordPress的WP Cron功能,设置每小时/每天自动执行一次导入函数
- 如果需要处理HTML格式邮件、附件,可以额外编写解析邮件结构的代码,将HTML正文、纯文本正文分开存储,附件保存到WordPress媒体库
内容的提问来源于stack exchange,提问作者Rohit kc
相关产品推荐
相关产品推荐

