2010-04-18 3 views
14

Я видел этот пост, но у меня это немного отличается:Как отправить электронную почту с многократным, динамической SMTP с использованием ActionMailer/Ruby On Rails

Rails ActionMailer with multiple SMTP servers

Я позволяя пользователям отправлять почту, используя свои собственные учетные данные SMTP так что на самом деле это происходит от них.

Но они будут отправлены из приложения Rails, поэтому для каждого пользователя мне необходимо отправить свои электронные письма с использованием собственного SMTP-сервера.

Как я могу это сделать?

+1

Пожалуйста, помогите получить это PR объединяется в рельсы. (https://github.com/rails/rails/pull/7397) Это делает именно то, о чем вы думаете. –

ответ

3

Просто установите значения параметров ActionMailer :: Base перед каждым действием отправки.

smtp_config = user.smtp_configuration 

ActionMailer::Base.username = smtp_config.username 
ActionMailer::Base.password = smtp_config.password 
ActionMailer::Base.server = .. 
ActionMailer::Base.port = .. 
ActionMailer::Base.authentication = .. 
+0

Как это сделать? Конфигурации ActionMailer находятся в файле конфигурации ... Создание локальной переменной smtp_config, а затем передать соответствующие методы? – Angela

+2

Так просто потерял мой предыдущий ответ, поэтому повторю попытку с более короткой нотой. Вы просто устанавливаете переменные класса ActionMailer в этих вызовах. Как правило, они определяются в конфигурациях, но вы можете изменять их в любое время. В вашем случае вы хотите установить их перед каждым методом доставки productXXX дочернего класса ActionMailer, который необходимо вызвать. – simianarmy

+2

Ответ jcalvert - правильный способ сделать это. –

55

Выполнение того, что описано в другом ответе, небезопасно; вы устанавливаете здесь переменные класса, а не инстантируемые переменные. Если ваш контейнер Rails разворачивается, вы можете это сделать, но теперь ваше приложение зависит от детали реализации контейнера. Если вы не открываете новый рубиновый процесс, вы можете иметь условия гонки здесь.

У вас должна быть модель, расширяющая ActionMailer :: Base, а при вызове метода она вернет объект Mail :: Message. Это ваш экземпляр объекта, и вы должны изменить свои настройки. Настройки также являются просто хешем, поэтому вы можете его встроить.

msg = MyMailer.some_message 
msg.delivery_method.settings.merge!(@user.mail_settings) 
msg.deliver 

Где в вышеуказанных mail_settings возвращает некоторую хэш с соответствующими ключами IE

{:user_name=>username, :password=>password} 
+0

Перехватчик ActionMailer (delivering_email) может быть полезным в некоторых случаях. –

+6

Пожалуйста, помогите получить этот PR, объединенный в рельсы. (https://github.com/rails/rails/pull/7397) Это делает то, о чем OP легко думает. –

+6

Запрос на pull, упомянутый @AdityaSanghi, был объединен с Rails 4+, но не будет исправлен в более ранних версиях. – plainjimbo

12

Вот решение, которое я придумал на основе предыдущих ответов и комментариев. Это использует ActionMailer interceptor class.

class UserMailer < ActionMailer::Base 
    default from: proc{ @user.mail_settings[:from_address] }  

    class DynamicSettingsInterceptor 
    def self.delivering_email(message) 
     message.delivery_method.settings.merge!(@user.mail_settings) 
    end 
    end 
    register_interceptor DynamicSettingsInterceptor 
end 
+0

Это идеальное решение и хорошо работает в Rails 3. –

9

Для Rails 3.2.x

Вы можете включить AbstractController :: обратные вызовы в классе почтовой программы и сделать "after_filter: set_delivery_options" внутри почтовой программы.

Метод set_delivery_options будет иметь доступ к переменным экземпляра, установленным вами в действии вашей почтовой программы, и вы можете получить доступ к почтовому объекту как «сообщение».

class MyNailer < ActionMailer::Base 
    include AbstractController::Callbacks 
    after_filter :set_delivery_options 

    def nail_it(user) 
    @user = user 
    mail :subject => "you nailed it" 
    end 

    private 

    def set_delivery_options 
    message.delivery_method.settings.merge!(@user.company.smtp_creds) 
    end 
end 
3

в случае кто-то должен установить способ доставки динамически вместе с учетными данными SMTP, и можно использовать Mail::Message instance method установить способ доставки вместе с его переменными поэтому мой addapted Aditya Sanghi версия:

class MainMailer < ActionMailer::Base 
    WHATEVER_CONDITION = true # example only f.e. @ser 

    include AbstractController::Callbacks 
    after_filter :set_delivery_options 

    private 
    def set_delivery_options 
    settings = { 
    :address => 'smtp.mandrillapp.com', # intentionally 
    :port => 587, # intentionally 
    :domain => 'your_domain', #insetad of localhost.localdomain' 
    :user_name => 'smtp_username', 
    :password => 'smtp_password', 
    :authentication => 'PLAIN' # or smthing else 
} 
    if WHATEVER_CONDITION 
     message.delivery_method(:smtp, settings) 
    end 
    end 
end 
+0

WHATEVER_CONDITION - постоянная класса, поэтому зачем вам вообще использовать его? – danmaz74

+0

вам не нужно это делать, моя точка зрения заключалась в том, что вы можете использовать какое-то условие, чтобы решить, нужно ли вам объединить (переписать) метод доставки почты или нет, сам я не использую константу здесь, мои другие почтовые отправления наследуют из класса MainMailer, и если выполняются некоторые условия, я использую другую конфигурацию smtp, что является главным моментом всего этого в моем случае. –

Смежные вопросы