gotthardp/rabbitmq-email

Doesn't send email when no AMQP headers are defined

artemliubymov opened this issue · 20 comments

Hi :)
I setup rabbitnmq-email, create configure, but when i try send email it's not work.
My rabbitmq.config file :

 [
 {rabbitmq_email, [
 %% gen_smtp server parameters
 %% see https://github.com/Vagabond/gen_smtp#server-example
 {server_config, [
   [{port, 2525}, {protocol, tcp}, {domain, "example.com"}, {address,    {0,0,0,0}}]
  ]},

%% inbound email exchanges: [{email-domain, {vhost, exchange}}, ...}
{email_domains, [
  {<<"example.com">>, {<<"/">>, <<"email-in">>}}
]},
{email_queues, [
  {{<<"/">>, <<"email-out">>}, <<"example.com">>}
]},

%% sender indicated in the From header
{client_sender, "test.ekadastr@yandex.ru"},

%% gen_smtp client parameters
%% see https://github.com/Vagabond/gen_smtp#client-example
{client_config, [
  {relay, "smtp.yandex.ru"}, {ssl, true}, {username, "myemail@yandex.ru"}, {password, "mypass"}
]}
]}
].

And that python code that i try:

import smtplib
from email.mime.text import MIMEText

me = "myemail@yandex.ru"
you = "klient_email@yandex.ru"

msg = MIMEText("Hello world!")
msg['From'] = me
msg['To'] = you
msg['Subject'] = 'Hello'
try:
   s = smtplib.SMTP('localhost', 2525)
   s.login("guest", "guest")
   s.sendmail(me, you, msg.as_string())
   s.quit()
   print('Success')
except: 
   print('fail')

When i run code, it's work and print 'Success', but email not send. In log file this:

 =INFO REPORT==== 30-Dec-2015::00:00:10 ===
 example.com SMTP connection from {127,0,0,1}

=INFO REPORT==== 30-Dec-2015::00:00:10 ===
EHLO from [127.0.0.1]

=INFO REPORT==== 30-Dec-2015::00:00:10 ===
text/plain message from test.ekadastr@yandex.ru to         
[<<"Artem.Liubymov@yandex.ru">>] queued as   
631952c2c7e75e246e44811c73e40b62

=INFO REPORT==== 30-Dec-2015::00:00:10 ===
{'EXIT',<0.11011.0>,normal}

Hi. You sent an e-mail in the broker, right? By email not send you mean that no e-mail (SMTP) was sent out of the broker, right? This is expected behavior; the broker does not relay e-mails unless configured to do so.

Yes i think i sent email in broker. I think in code i do this with this parametres for SMTP:

s = smtplib.SMTP('localhost', 2525)
  s.login("guest", "guest")

Is it right?
If it is right, how can i configured to send e-mails?

Yes, that is right. If you want to send an e-mail, you should send an AMQP message to the email-out queue.

Sorry for stupid questions, but how can i send an AMQP message to the email-out ?

Have a look at the tutorial and do something like this:

channel.basic_publish(exchange='',
                      routing_key='email-out',
                      body=message,
                      properties=pika.BasicProperties(
                         delivery_mode = 2, # make message persistent
                      ))

This uses the default exchange and routes the message directly to the email-out queue.

My code now:

import smtplib
from email.mime.text import MIMEText
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='email-out')


me = "test.ekadastr@yandex.ru"
you = "Artem.Liubymov@yandex.ru"

msg = MIMEText("Hello world!")
msg['From'] = me
msg['To'] = you
msg['Subject'] = 'Hello'
try:
s = smtplib.SMTP('localhost', 2525)
s.login("guest", "guest")
s.sendmail(me, you, msg.as_string())
channel.basic_publish(exchange='',
                  routing_key='email-out',
                  body=msg.as_string(),
                  properties=pika.BasicProperties(
                     delivery_mode = 2, # make message persistent
                  ))
s.quit()

print('Success')
except: 
print('fail')
connection.close()

But i get error:

Traceback (most recent call last):
  File "send.py", line 8, in <module>
    channel.queue_declare(queue='email-out')
  File "/home/artem/repozitoriy/rab/vevn/lib/python3.4/site-    
packages/pika/adapters/blocking_connection.py", line 2329, in queue_declare
 self._flush_output(declare_ok_result.is_ready)
  File "/home/artem/repozitoriy/rab/vevn/lib/python3.4/site-    
packages/pika/adapters/blocking_connection.py", line 1181, in _flush_output
    raise exceptions.ChannelClosed(method.reply_code, method.reply_text)
pika.exceptions.ChannelClosed: (406, "PRECONDITION_FAILED - inequivalent arg 'durable' for   
 queue 'email-out' in vhost '/': received 'false' but current is 'true'")

I think thi say that email-out is created. Right?

@ArtemLubimov

pika.exceptions.ChannelClosed: (406, "PRECONDITION_FAILED - inequivalent arg 'durable' for   
 queue 'email-out' in vhost '/': received 'false' but current is 'true'")

means your queue declaration fails because the queue already exists with different properties, closing the channel (after which it cannot be used). Delete it and it will succeed.

Thanks, it's work but e-mail, don't send. Log for operation:

=INFO REPORT==== 30-Dec-2015::02:21:23 ===
accepting AMQP connection <0.12438.0> (127.0.0.1:54725 -> 127.0.0.1:5672)

=INFO REPORT==== 30-Dec-2015::02:21:23 ===
example.com SMTP connection from {127,0,0,1}

=INFO REPORT==== 30-Dec-2015::02:21:23 ===
EHLO from [127.0.0.1]

=ERROR REPORT==== 30-Dec-2015::02:21:23 ===
** Generic server <0.12406.0> terminating 
** Last message in was {{'basic.deliver',<<"example.com">>,1,false,<<>>,
                        <<"email-out">>},
                    {amqp_msg,
                        {'P_basic',undefined,undefined,undefined,2,
                            undefined,undefined,undefined,undefined,
                            undefined,undefined,undefined,undefined,
                            undefined,undefined},
                        <<"Content-Type: text/plain; charset=\"us-ascii\"\nMIME-Version: 1.0\nContent-   
Transfer-Encoding: 7bit\nFrom: test.ekadastr@yandex.ru\nTo:   
Artem.Liubymov@yandex.ru\nSubject: Hello\n\nHello world!">>}}
** When Server state == {state,<0.12409.0>,<0.12422.0>}
** Reason for termination == 
** {function_clause,
   [{lists,map,
        [#Fun<rabbit_message_handler.0.21905753>,undefined],
        [{file,"lists.erl"},{line,1237}]},
    {rabbit_message_handler,handle_info,2,
        [{file,"src/rabbit_message_handler.erl"},{line,63}]},
    {gen_server,try_dispatch,4,[{file,"gen_server.erl"},{line,615}]},
    {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,681}]},
    {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]}

=INFO REPORT==== 30-Dec-2015::02:21:23 ===
text/plain message from test.ekadastr@yandex.ru to [<<"Artem.Liubymov@yandex.ru">>] queued   
as bac31a45ec77de4c9975114558ba4077

=INFO REPORT==== 30-Dec-2015::02:21:23 ===
{'EXIT',<0.12471.0>,normal}

=INFO REPORT==== 30-Dec-2015::02:21:23 ===
closing AMQP connection <0.12438.0> (127.0.0.1:54725 -> 127.0.0.1:5672) 

Anybody now what seems this error and how can i feex it?

There are 3 things that should be fixed:

  • This error message says you did something unexpected. Did you include any AMQP properties and/or headers in your message?
  • In any case, the error message shows you are sending MIME headers in the AMQP messages. This is not how it works: if you want to send a MIME header, you should create an AMQP header. See here.
  • I gave you a wrong advice (sorry for that): you should create an exchange (e.g. 'X') and bind it to the queue 'email-out'. Then you should send the AMQP message as:
channel.basic_publish(exchange='X',
                  routing_key='Artem.Liubymov@yandex.ru',
                  body=msg.as_string(),
                  properties=pika.BasicProperties(
                     delivery_mode = 2, # make message persistent
                  ))

I should probably create some Python example.

Hi, I fix you remark and now in log rabbitmq i haven't any errors, but email don't send.
My config file:

   [
   {rabbitmq_email, [
   %% gen_smtp server parameters
   %% see https://github.com/Vagabond/gen_smtp#server-example
  {server_config, [
    [{port, 2525}, {protocol, tcp}, {domain, "example.com"}, {address,    {0,0,0,0}}]
    ]},

 %% inbound email exchanges: [{email-domain, {vhost, exchange}}, ...}
  {email_domains, [
   {<<"example.com">>, {<<"/">>, <<"email-in">>}}
  ]},
 {email_queues, [
  {{<<"/">>, <<"email-out">>}, <<"example.com">>}
]},

%% sender indicated in the From header
{client_sender, "test.ekadastr@yandex.ru"},

%% gen_smtp client parameters
%% see https://github.com/Vagabond/gen_smtp#client-example
{client_config, [
  {relay, "smtp.yandex.ru"}, {ssl, true}, {username, "test.ekadastr@yandex.ru"}, {password,   
   "mypass"}
 ]}
 ]}
 ].

My Python code:

 import smtplib
 from email.mime.text import MIMEText
 import pika

 connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 channel = connection.channel()

 me = "test.ekadastr@yandex.ru"
you = "Artem.Liubymov@yandex.ru"

try:
     s = smtplib.SMTP('localhost', 2525)
     s.login("guest", "guest")
     msg='lalala'
     channel.exchange_declare(exchange='X', type='topic')
     channel.queue_bind(exchange='X', queue='email-out')
     channel.basic_publish(exchange='X',
                  routing_key='Artem.Liubymov@yandex.ru',
                  body=msg,
                  properties=pika.BasicProperties(
                     delivery_mode = 2, # make message persistent
                  ))    
     s.sendmail(me, you, msg)

     s.quit()

    print('Success')
 except: 
     print('fail')
 connection.close()

And log file:

 =INFO REPORT==== 5-Jan-2016::17:28:10 ===
 accepting AMQP connection <0.10076.0> (127.0.0.1:42765 -> 127.0.0.1:5672)

 =INFO REPORT==== 5-Jan-2016::17:28:10 ===
 example.com SMTP connection from {127,0,0,1}

 =INFO REPORT==== 5-Jan-2016::17:28:10 ===
 EHLO from [127.0.0.1]

 =INFO REPORT==== 5-Jan-2016::17:28:10 ===
 text/plain message from test.ekadastr@yandex.ru to [<<"Artem.Liubymov@yandex.ru">>] queued  
  as a0373a758631126ca5ed1c183d623035

 =INFO REPORT==== 5-Jan-2016::17:28:10 ===
 {'EXIT',<0.10106.0>,normal}

 =INFO REPORT==== 5-Jan-2016::17:28:10 ===
 closing AMQP connection <0.10076.0> (127.0.0.1:42765 -> 127.0.0.1:5672)

What's wrong? Why email not send? O, and if i try send message to not exist email, on my email test.ekadastr(sender) i haven't message that message was not delivered. I think test.ekadastr@yandex.ru don't send message, or it from queue dont send. What wrong, can explain me please?:)

I think the message you send does not get routed to the 'email-out' queue.
If you use a topic exchange, you need to define a binding key. In your code try

channel.queue_bind(exchange='X', queue='email-out', routing_key='#')

Code work with Success, but in log one error:

=INFO REPORT==== 6-Jan-2016::07:16:34 ===
accepting AMQP connection <0.9564.0> (127.0.0.1:46969 -> 127.0.0.1:5672)

 =INFO REPORT==== 6-Jan-2016::07:16:34 ===
 example.com SMTP connection from {127,0,0,1}

=INFO REPORT==== 6-Jan-2016::07:16:34 ===
EHLO from [127.0.0.1]

=INFO REPORT==== 6-Jan-2016::07:16:34 ===
text/plain message from test.ekadastr@yandex.ru to [<<"Artem.Liubymov@yandex.ru">>] queued   
as bf2286176de3f5a9521f02a6e8fd11ec

=INFO REPORT==== 6-Jan-2016::07:16:34 ===
 {'EXIT',<0.9594.0>,normal}

 =ERROR REPORT==== 6-Jan-2016::07:16:34 ===  

** Generic server <0.272.0> terminating 
** Last message in was {{'basic.deliver',<<"example.com">>,1,false,<<"X">>,
                        <<"Artem.Liubymov@yandex.ru">>},
                    {amqp_msg,
                        {'P_basic',undefined,undefined,undefined,2,
                            undefined,undefined,undefined,undefined,
                            undefined,undefined,undefined,undefined,
                            undefined,undefined},
                        <<"lalala">>}}
 ** When Server state == {state,<0.275.0>,<0.288.0>} 
** Reason for termination == 
** {function_clause,
   [{lists,map,
        [#Fun<rabbit_message_handler.0.21905753>,undefined],
        [{file,"lists.erl"},{line,1237}]},
    {rabbit_message_handler,handle_info,2,
        [{file,"src/rabbit_message_handler.erl"},{line,63}]},
    {gen_server,try_dispatch,4,[{file,"gen_server.erl"},{line,615}]},
    {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,681}]},
    {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]}

 =INFO REPORT==== 6-Jan-2016::07:16:34 ===
 closing AMQP connection <0.9564.0> (127.0.0.1:46969 -> 127.0.0.1:5672)

Well, this is a bug. As a workaround, please set some AMQP header while sending the message. For example:

    channel.basic_publish(exchange='',
                  routing_key='email-out',
                  body=msg.as_string(),
                  properties=pika.BasicProperties(
                     delivery_mode = 2, # make message persistent
                     content_type = 'text/plain',
                     headers = {'subject':'whatever'},
                  ))

Thanks for reporting this.

Fixed by 91fad08

Yes, I send email with this code:

 import smtplib
 from email.mime.text import MIMEText
 import pika

 connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
  channel = connection.channel()



 me = "test.ekadastr@yandex.ru"
 you = "ArtemLiubymov@yandex.ru"


 try:
     s = smtplib.SMTP('localhost', 2525)
     s.login("guest", "guest")
     msg='lalala'
     channel.exchange_declare(exchange='X', type='topic')
     channel.queue_bind(exchange='X', queue='email-out', routing_key='#')


     channel.basic_publish(exchange='X',
                   routing_key='ArtemLiubymov@yandex.ru',
                   body=msg,
                   properties=pika.BasicProperties(
                      delivery_mode = 2, # make message persistent
              content_type = 'text/plain',
                      headers = {'header':'whatever'}
                  ))        

     s.sendmail(me, you, msg)#msg.as_string())  
     s.quit()

     print('Success')
 except: 
     print('fail')
 connection.close()

This is right?:)

Yes, that should be right. Does it work? :)

Yes, it work:) Thank you very much:)Why in channel.basic_publish routing_key='email-to-send'?

Well, because the system is designed that way; there is no special reason for that. Some explanation is here.

Thank you very much for help and explanations:)