2010-04-18 11 views
14

J'ai vu ce post, mais le mien est un peu différent:Comment envoyer des e-mails avec des multiples, smtp dynamique à l'aide actionmailer/Ruby on Rails

Rails ActionMailer with multiple SMTP servers

Je suis ce qui permet aux utilisateurs d'envoyer des messages en utilisant leurs propres informations d'identification SMTP donc ça vient vraiment d'eux.

Mais ils seront envoyés à partir de l'application Rails, ce qui signifie pour chaque utilisateur que j'ai besoin d'envoyer leurs e-mails en utilisant leur propre serveur SMTP.

Comment puis-je faire cela?

+1

S'il vous plaît aider à obtenir ce PR fusionné dans les rails. (https://github.com/rails/rails/pull/7397) Cela fait exactement ce que vous pensez facilement. –

Répondre

3

Définissez simplement les valeurs de configuration ActionMailer :: Base avant chaque action d'envoi.

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

Comment je fais ça? Les configurations d'ActionMailer sont dans le fichier de configuration ... Créer une variable locale appelée smtp_config et passer les méthodes respectives? – Angela

+2

SO vient de perdre ma réponse précédente, essayant à nouveau avec une note plus courte. Vous définissez simplement des variables de classe ActionMailer dans ces appels. Typiquement, ils sont définis dans les configs, mais vous pouvez les changer quand vous le voulez. Dans votre cas, vous souhaitez les définir avant la méthode deliver_XXX de chaque classe enfant ActionMailer que vous devez appeler. – simianarmy

+2

La réponse de jcalvert est la bonne façon de le faire. –

55

Faire ce qui est décrit dans l'autre réponse n'est pas sûr; vous définissez des variables de classe ici, pas des variables instanciées. Si votre conteneur Rails est forking, vous pouvez le faire, mais votre application dépend maintenant d'un détail d'implémentation du conteneur. Si vous n'êtes pas en train de forger un nouveau processus Ruby, alors vous pouvez avoir une condition de concurrence ici.

Vous devriez avoir un modèle qui étend ActionMailer :: Base, et lorsque vous appelez une méthode, il retournera un objet Mail :: Message. C'est votre objet d'instance et c'est là que vous devriez changer vos paramètres. Les paramètres sont également juste un hachage, de sorte que vous pouvez en ligne.

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

Où dans les mail_settings ci-dessus renvoie une table de hachage avec les touches appropriées IE

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

Intercepteur d'ActionMailer (deliver_email) peut être utile dans certains cas. –

+6

S'il vous plaît aider à obtenir ce PR fusionné dans les rails. (https://github.com/rails/rails/pull/7397) Cela fait exactement ce que OP pense facilement. –

+6

La requête d'extraction mentionnée par @AdityaSanghi a été fusionnée dans Rails 4+ mais ne sera pas corrigée dans les versions antérieures. – plainjimbo

12

Voici une solution que je suis venu avec sur la base des réponses précédentes et commentaires. Cela utilise un 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

Ceci est une solution idéale et fonctionne bien dans Rails 3. –

9

Pour Rails 3.2.x

Vous pouvez inclure AbstractController :: dans votre classe Callbacks mailer et faire un "after_filter: set_delivery_options" à l'intérieur du logiciel de messagerie. La méthode set_delivery_options aurait accès aux variables d'instance configurées par vous dans votre action mailer et vous pouvez accéder à l'objet courrier sous la forme "message".

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

au cas où quelqu'un a besoin de définir la méthode de distribution dynamique avec les informations d'identification de smtp, u peut utiliser Mail::Message instance method pour définir le mode de livraison avec elle les variables est si ma addapted Aditya Sanghi version:

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 est une constante de classe, alors, pourquoi avez-vous besoin de l'utiliser du tout? – danmaz74

+0

vous ne devez pas faire cela, mon point ici était que vous pouvez utiliser une condition pour décider si vous avez besoin de fusionner (réécrire) la méthode de livraison de courrier ou non, moi je n'utilise pas ici, mes autres expéditeurs héritent de la classe MainMailer et si certaines conditions sont remplies j'utilise une configuration smtp différente, ce qui est le point principal de tout cela dans mon cas. –