-1

I am trying to send an email from a cronjob via smtplib. Running the python-script as user or as root works correctly, however as a cron-job I "think" I get problems connecting to the server. The code itself is the following:

import smtplib, ssl
from datetime import datetime

def send_mail(subject, mail_text, to_addr):
    FROM = "myaddress@gmail.com"
    SUBJECT = subject

    TEXT = (mail_text)

    mail_user=FROM
    mail_password="<password>"
    message = """From: %s\nTo: %s\nSubject: %s\n\n%s
    """ % (FROM, TO, SUBJECT, TEXT)
    print("message")
    print(message)
    try:
        print("a")
        server = smtplib.SMTP_SSL("smtp.gmail.com", 465)
        print(server)
        print("b")
        print(server.ehlo())
        print("Login on Server")
        print(server.login(mail_user, mail_password))
        print("Sending Mail")
        print(server.sendmail(FROM, TO, message))
        print("Closing Connection")
        server.close()
        print('Successfully sent the mail')
    except Exception as e:
        print( "failed to send mail")


subject="Start-Test"
mail_text="Cron-Job started"
to_addr="somewhere@example.com"
print ("Job started:")
print datetime.now()

send_mail(subject, mail_text, to_addr)

If I run the code from the command-line via "python " I get the following output:

<module 'smtplib' from '/usr/lib/python2.7/smtplib.pyc'> 
Job started: 2020-01-02 14:06:31.20274

message From: myaddress@gmail.com 
To: somewhere@example.com 
Subject: Start-Test 
Cron-Job started 
a 
<smtplib.SMTP_SSL instance at 0x76bbab48> 
b 
(250, 'smtp.gmail.com at your service, [92.211.42.193]\nSIZE 35882577\n8BITMIME\nAUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\nENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8') 
Login on Server (235, '2.7.0 Accepted') 
Sending Mail {} 
Closing Connection

However if I run the same script from the cronjob with printing the outputs into a file I get the following:

<module 'smtplib' from '/usr/lib/python2.7/smtplib.pyc'>
Job started:
2020-01-02 14:06:53.229564
message
From: myaddress@gmail.com
To: somewhere@example.com
Subject: Start-Test

Cron-Job started

a
failed to send mail

The behaviour is identical whether I have the cronjob brought in either way: "sudo crontab -e" or "crontab -e". In both crontabs I have the following entry (one at a time):

@reboot python /my_script.py > /logfile.txt

In another script I printed the PATH-variable and that is identical between the command-line and the cron-tab.

Any idea where this is going wrong? The smtplib seems to be correctly found based on the print-statement, also the python-interpreter. Thanks a lot already in advance!

Moadl

ye_ol_man
  • 37
  • 6
  • I tried both suggestions now, the pointer to actually print the real error is well taken. The initial error now after a startup wait-time of 60 seconds was [Errno -3] Temporary failure in name resolution This I "fixed" by putting in the direct IP-address which I took from a ping-response. After that I am now getting: "[Errno 101] Network is unreachable". At that time the network is already up an running for a "long" time which I can "prove" by connecting via putty. – ye_ol_man Jan 02 '20 at 18:11
  • At reboot? You can connect with PuTTY while it's booting? Very certainly not. – tripleee Jan 03 '20 at 09:09
  • @tripleee: I can connect via putty ~20 seconds after I fired off the reboot command. The sleep I had in was for 60 seconds. – ye_ol_man Jan 03 '20 at 13:09
  • There is no `sleep` in the code you posted. In any event, I definitely trust the "network unavailable" error message here. – tripleee Jan 03 '20 at 13:12

2 Answers2

0

my answer got deleted, although i think it's still the correct answer, maybe Jean-Francois is much more wise and can post a correcting reply/comment instead of deleting mine.

So i will just repost it...


Probably network won't be available yet, when your script is running after reboot, so smtplib fails to connect to the SMTP server. You can add a short sleep to your cronjob, or maybe add retrying to your python script.

In order to know what exactly is going wrong, you can print your exception.


A Network is unreachable is still related to a network failure, you just ignored the DNS resolution error (Temporary failure in name resolution) by hardcoding the IP.

In order to double check, just run a @reboot cron with ping -c 4 8.8.8.8 > /tmp/ping_result.

olisch
  • 960
  • 6
  • 11
  • I currently cannot access the system and look at it again next week. The sleep that I put in is not in the original code above but at the moment via a shell-script that slleps for 60 seconds and then calls the python-script. My current work-around is a daily reboot at a stupid time and a scheduled start via a normal timed cronjob. – ye_ol_man Jan 03 '20 at 16:51
0

OK, after a bit of time off the system the situation is sorted. Issue is the network unreachable and similar in the initial time after booting as @olisch suggested and the pointer from @snakecharmerb and @tripleee.

Several points for anyone else lateron reading this post and for debugging: - output from crontab into file: " > file" alone will not be enough as this will not be printing errors. " > file 2>&1" will also contain error-messages - crontab-calls to scripts require the full path in the system: When working on the scripts the usual command during testing is: python ./my_file.py However the cron-script will not be in that directory, hence use the full path python /home/myname/directory/my_file.py ==> again, if 2>&1 is used in the call then a "file not found message" will be printed.

ye_ol_man
  • 37
  • 6