Mailman多次保存邮件



我已经将Mailman Gem集成到了我的Rails项目中。它成功地从Gmail那里获取了电子邮件。在我的应用程序中,我的电子邮件有一个模型消息。这些电子邮件被正确保存为消息模型。

问题在于,电子邮件有时会保存多次,我无法识别模式。有些电子邮件保存了一次,大约两次,有些保存了三遍。

,但我找不到代码中的故障。

这是我的Mailman_server脚本:

脚本/Mailman_server

#!/usr/bin/env ruby
# encoding: UTF-8
require "rubygems"
require "bundler/setup"
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'mailman'
Mailman.config.ignore_stdin = true
#Mailman.config.logger = Logger.new File.expand_path("../../log/mailman_#{Rails.env}.log", __FILE__)
if Rails.env == 'test'
  Mailman.config.maildir = File.expand_path("../../tmp/test_maildir", __FILE__)
else
  Mailman.config.logger = Logger.new File.expand_path("../../log/mailman_#{Rails.env}.log", __FILE__)
  Mailman.config.poll_interval = 15
  Mailman.config.imap = {
    server: 'imap.gmail.com',
    port: 993,  # usually 995, 993 for gmail
    ssl: true,
    username: 'my@email.com',
    password: 'my_password'
  }
end
Mailman::Application.run do
  default do
    begin
      Message.receive_message(message)
    rescue Exception => e
      Mailman.logger.error "Exception occurred while receiving message:n#{message}"
      Mailman.logger.error [e, *e.backtrace].join("n")
    end
  end
end

电子邮件在我的消息类中处理:

  def self.receive_message(message)
    if message.from.first == "my@email.com"
      Message.save_bcc_mail(message)
    else
      Message.save_incoming_mail(message)
    end
  end
  def self.save_incoming_mail(message)
    part_to_use = message.html_part || message.text_part || message
    if Kontakt.where(:email => message.from.first).empty?
      encoding = part_to_use.content_type_parameters['charset']
      Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.from.first, inbound: true, time: message.date
    else
      encoding = part_to_use.content_type_parameters['charset']
      Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.from.first, inbound: true, time: message.date, messageable_type: 'Company', messageable_id: Kontakt.where(:email => message.from.first).first.year.id
    end
  end
  def self.save_bcc_mail(message)
    part_to_use = message.html_part || message.text_part || message
    if Kontakt.where(:email => message.to.first).empty?
      encoding = part_to_use.content_type_parameters['charset']
      Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.to.first, inbound: false, time: message.date
    else
      encoding = part_to_use.content_type_parameters['charset']
      Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.to.first, inbound: false, time: message.date, messageable_type: 'Company', messageable_id: Kontakt.where(:email => message.to.first).first.year.id
    end
  end

我使用此脚本宣讲了Mailman_server:

脚本/Mailman_daemon

#!/usr/bin/env ruby
require 'rubygems'  
require "bundler/setup"  
require 'daemons'
Daemons.run('script/mailman_server') 

我与Capistrano一起部署。

这是负责停止,启动和重新启动我的Mailman_server的部分:

脚本/decloy.rb

set :rails_env, "production" #added for delayed job  
after "deploy:stop",    "delayed_job:stop"
after "deploy:start",   "delayed_job:start"
after "deploy:restart", "delayed_job:restart"
after "deploy:stop",    "mailman:stop"
after "deploy:start",   "mailman:start"
after "deploy:restart", "mailman:restart"
namespace :deploy do
  desc "mailman script ausfuehrbar machen"
  task :mailman_executable, :roles => :app do
   run "chmod +x #{current_path}/script/mailman_server"
  end
  desc "mailman daemon ausfuehrbar machen"
  task :mailman_daemon_executable, :roles => :app do
   run "chmod +x #{current_path}/script/mailman_daemon"
  end
end
namespace :mailman do  
  desc "Mailman::Start"
  task :start, :roles => [:app] do
   run "cd #{current_path};RAILS_ENV=#{fetch(:rails_env)} bundle exec script/mailman_daemon start"
  end
  desc "Mailman::Stop"
  task :stop, :roles => [:app] do
   run "cd #{current_path};RAILS_ENV=#{fetch(:rails_env)} bundle exec script/mailman_daemon stop"
  end
  desc "Mailman::Restart"
  task :restart, :roles => [:app] do
   mailman.stop
   mailman.start
  end
end

是否可以在我的部署中启动多个邮件服务器的实例,然后每个实例几乎同时进行轮询?第一个实例之前的第二个和第三个实例将电子邮件标记为读取并进行轮询和处理电子邮件?

更新30.01。

我将投票间隔设置为60秒。但这一切都没有改变。

我检查了存储邮递员PID文件的文件夹。只有一个邮递员PID文件。因此,绝对只有一台邮递服务器运行。我检查了日志文件,可以看到消息被多次获取:

Mailman v0.7.0 started
IMAP receiver enabled (my@email.com).
Polling enabled. Checking every 60 seconds.
Got new message from 'my.other@email.com' with subject 'Test nr 0'.
Got new message from 'my.other@email.com' with subject 'Test nr 1'.
Got new message from 'my.other@email.com' with subject 'test nr 2'.
Got new message from 'my.other@email.com' with subject 'test nr 2'.
Got new message from 'my.other@email.com' with subject 'test nr 3'.
Got new message from 'my.other@email.com' with subject 'test nr 4'.
Got new message from 'my.other@email.com' with subject 'test nr 4'.
Got new message from 'my.other@email.com' with subject 'test nr 4'.

在我看来,这个问题肯定在我的Mailman服务器代码中。

更新31.1。

在我看来,这与我的生产机器有关。当我通过完全相同的配置在开发中进行测试(将我的本地数据库从SQLite更改为今天早上的MySQL进行测试),就像在生产机器上一样,我没有重复。我的代码可能一切正常,但是生产机器存在问题。会问我的寄养者是否可以看到解决方案。为了解决这个问题,我将随着Ariejan的建议。

解决方案:我发现了这个问题。我部署到一台机器,其中TMP目录是所有版本之间共享的计算机。我忘了定义邮递的PID文件应保存的路径。因此,它保存在脚本目录中,而不是/tmp/pids目录中。因此,在新部署后无法停止旧的Mailman_daemon。这导致了一支工作的Mailman_daemons大军,这些大军对我的MailAccount进行了调查...杀死所有这些过程后,一切都很好!不再重复!

这可能是某些并发/计时问题。例如。在保存当前处理的邮件之前,将进口新邮件。


编辑:刚刚注意到您将Mailman.config.poll_interval设置为15。这意味着它将每15秒检查一次新消息。尝试将此值增加到默认的60秒。无论采用哪种设置,添加我下面提到的重复数据删除代码可能是一个好主意。


我的提示也是从每封电子邮件中存储message_id,以便您可以轻松地发现重复。

而不是:

Message.create(...)

做:

# This makes sure you have the latest pulled version.
message = Message.find_or_create(message_id: message.message_id)
message.update_attributes(...)
# This makes sure you only import it once, then ignore further duplicates.
if !Message.where(message_id: message.message_id).exists?
  Message.create(...)
end

有关message_id的更多信息:http://rdoc.info/github/mikel/mail/mail/mail/message#message_id-instance_method

请记住,电子邮件和IMAP并不意味着像您期望Postgres或MySQL那样成为一致的数据存储。希望这可以帮助您整理出重复的邮件。

我发现了问题。我部署到一台机器,其中TMP目录是所有版本之间共享的计算机。我忘了定义邮递的PID文件应保存的路径。因此,它保存在脚本目录中,而不是/tmp/pids目录中。因此,在新部署后无法停止旧的Mailman_daemon。这导致了一支工作的Mailman_daemons大军,这些大军对我的MailAccount进行了调查...杀死所有这些过程后,一切都很好!不再重复!

最新更新