django_cron not sending email - python

I have just installed django_cron not django_crontab though, somehow I am trying to send an email as notification but it just wouldn't work.
this is just for testing purpose so I set it to 1 minute.
the code was a bit more complex before but it didn't work so I used the most simplified way to send email in order to make sure that it's not working. Also even used it as a post method to test, and it tested out working perfectly if a post method called the follow codes
class MyCronJob(CronJobBase):
RUN_EVERY_MINS = 1 # every minute
schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
code = 'Email_Test' # a unique code
def do(self):
print('######################################')
send_mail(
'Subject here from cron',
'Here is the message.',
'from#email.com',
['to#emailcom'],
fail_silently=False,
)
I tried running python manage.py runcrons and python manage.py runcrons --force and waited, (no errors, I also added the print because I want to see if the code even runs and good, I see the ################# got printed)
can someone please give me an advise?
Thanks in advance

Try a custom function for sending mail. I tried send_mail function and it did not work for me and i did not find any bug or explanation on this topic. Below is an example of sending html emails using smtplib.
import smtplib
def send_email(email, subject, message):
text = subject
html = message
msg = MIMEMultipart('alternative')
html_part = MIMEText(html, 'html')
text_part = MIMEText(text, 'plain')
msg.attach(text_part)
msg.attach(html_part)
msg['Subject'] = subject
msg['From'] = SENDER_EMAIL
msg['To'] = email
s = smtplib.SMTP(settings.GMAIL_SMTP)
s.ehlo()
s.starttls()
s.login(SENDER_EMAIL, SENDER_PASSWORD)
s.sendmail(SENDER_EMAIL, email, msg.as_string())
s.quit()

please make sure first you must have to import library from django.core.mail, to using send_mail. I know it's too late to help, but u can try this..
from django_cron import CronJobBase, Schedule
from django.core.mail import send_mail
class my_scheduled_job(CronJobBase):
RUN_EVERY_MINS = 1
schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
code = 'user_dashboard.autoemail.my_scheduled_job'
def do(self):
subject= 'Send Email With Automatic Schedule'
message= 'Test send email :'
email_to= ['xxxxxxxx#gmail.com']
email_user(subject_test, message_test, email_to_test)
print ("done")
def email_user(subject, message, email_to):
email_from = 'noreply#xxxx.id'
send = send_mail(subject, message, email_from, email_to)
return send

Related

How to automate python scripts on a web apache server

I want to create an automatic script in python that will inform me with an email when a new order is placed on my website.
So far, I found I can use cronjobs from the apache server every minute, but it seems to be overkill since I don't get orders every minute.
So I'm looking for a better solution.
Here’s the code you can call this code whenever the order is placed by the user you don’t need to automate
If you are using django you can use this:
from django.core.mail import send_mail
send_mail(
'Subject here',
'Here is the message.',
'from#example.com',
['to#example.com'],
fail_silently=False,
)
Without django you can use this :
import smtplib
sender = 'from#example.com'
receivers = ['to#example.com']
message = “This is a test e-mail message."
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print "Successfully sent email"
except SMTPException:
print "Error: unable to send email"

Sending an email in celery while running the rest of the method

Im trying to make my request to a page faster by having the send email part done through celery so that way the rest of the method can run and finish without having to wait for the email to be sent.
Ive tried using async and making a celery call before but I am unskilled and need a little help in that department
def checkout():
if request.method == 'POST':
username = User.get_username(session['email'])
#todo: do the next line in celery
send_email(username, session['email_to'])
session['email_to'] = None
flash('Youre request has been sent')
return redirect(url_for('home'))
return render_template('transaction/checkout.html')
send_email.py
def send_email(username_from, email):
from_email = os.get('email')
from_password = 'rnmmhgtlcaqsxows'
to_email = os.get('email')
subject = f'New Request from {username_from}'
message = f"You have a request from {username_from}"
msg = MIMEText(message, 'html')
msg['subject'] = subject
msg['To'] = to_email
msg['From'] = from_email
gmail = smtplib.SMTP('smtp.gmail.com',587)
gmail.ehlo()
gmail.starttls()
gmail.login(from_email, from_password)
gmail.send_message(msg)
Imagine send_email is a Celery task. - It would be sufficient to have
send_email.apply_async()
in your code to put that task on the default Celery queue, and it will be picked and executed by Celery, while the rest of the code continues working.

How to send message to multiple recipients?

I'm having some trouble sending a message to multiple addresses using the Gmail API. I've successfully sent a message to only one address, but get the following error when I include multiple comma-separated addresses in the 'To' field:
An error occurred: <HttpError 400 when requesting
https://www.googleapis.com/gmail/v1/users/me/messages/send?alt=json
returned "Invalid to header">
I'm using the CreateMessage and SendMessage methods from this Gmail API guide:
https://developers.google.com/gmail/api/guides/sending
That guide states that the Gmail API requires messages that are RFC-2822 compliant. I again didn't have much luck using some of these addressing examples in the RFC-2822 guide:
https://www.rfc-editor.org/rfc/rfc2822#appendix-A
I'm under the impression that 'mary#x.test, jdoe#example.org, one#y.test' should be a valid string to pass into the 'to' parameter of CreateMessage, but the error that I received from SendMessage leads me to believe otherwise.
Please let me know if you can recreate this problem, or if you have any advice on where I may be making a mistake. Thank you!
Edit: Here is the actual code that yields an error...
def CreateMessage(sender, to, subject, message_text):
message = MIMEText(message_text)
message['to'] = to
message['from'] = sender
message['subject'] = subject
return {'raw': base64.urlsafe_b64encode(message.as_string())}
def SendMessage(service, user_id, message):
try:
message = (service.users().messages().send(userId=user_id, body=message)
.execute())
print 'Message Id: %s' % message['id']
return message
except errors.HttpError, error:
print 'An error occurred: %s' % error
def ComposeEmail():
# build gmail_service object using oauth credentials...
to_addr = 'Mary Smith <mary#x.test>, jdoe#example.org, Who? <60one#y.test>'
from_addr = 'me#address.com'
message = CreateMessage(from_addr,to_addr,'subject text','message body')
message = SendMessage(gmail_service,'me',message)
Getting "Invalid to header" when sending with multiple recipients (comma delimited) in a single header was a regression that was fixed on 2014-08-25.
As James says in its comment, you shouldn't waste time trying to use Gmail API when Python has excellent documented support for using SMTP : email module can compose message including attachements, and smtplib sends them. IMHO you could use Gmail API for what works out of the box but should use the robust modules form Python Standard Library when things go wrong.
It looks like you want to send a text only message : here is a solution adapted from the email module documentation and How to send email in Python via SMTPLIB from Mkyong.com:
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.mime.text import MIMEText
msg = MIMEText('message body')
msg['Subject'] = 'subject text'
msg['From'] = 'me#address.com'
msg['To'] = 'Mary Smith <mary#x.test>, jdoe#example.org, "Who?" <60one#y.test>'
# Send the message via Gmail SMTP server.
gmail_user = 'youruser#gmail.com'
gmail_pwd = 'yourpassword'smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver = smtplib.SMTP('smtp.gmail.com')smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(gmail_user, gmail_pwd)
smtpserver.send_message(msg)
smtpserver.quit()
See also User.drafts reference - error"Invalid to header"
Apparently this bug was recently introduced in Gmail API.

Can I get the incoming message by using Mailgun?

A use Mailgun to send b a email, after b receive the email and reply to a.If I want to track the email coming from b, How I can get the email?
Here is the code:
1.sendmail.py
from smtplib import SMTP
import requests
login_name = "postmaster#zzb.mailgun.org"
password = "********"
def send_message_via_smtp():
smtp = SMTP("smtp.mailgun.org", 587)
smtp.login(login_name, password)
smtp.sendmail("zebozhuang#163.com","348284770#qq.com", "Subject:mailgun test \n\n just for test.\n\n")
smtp.quit()
if __name__=="__main__":
send_message_via_smtp()
2.create_route.py
import requests
from werkzeug.datastructures import MultiDict
def create_route():
return requests.post(
"https://api.mailgun.net/v2/routes",
auth=("api", "key-9c4-t2q6fouilngjummvtv1rge7t00f2"),
data=MultiDict([("priority", 1),
("description", "Sample route"),
("expression", "match_recipient('.*#qq.com')"),
("action", "forward('qiyazhuang#gmail.com')"),
("action", "stop()")])
)
I create the route and I run the script sendmail.py.After someone who use email 348284770#qq.com reply to the other who use email zebozhuang#163.com, the Gmail
can not receive the message by using the Mailgun method 'forward'.
Could anyone tell me why?
Your messages are likely being delivered. Check the "Logs" tab of the Mailgun Control Panel.
Do you see any entries that look like this:
Routed: .*#qq.com -> qiyazhuang#gmail.com 'SUBJECT HERE'
The "Routed" prefix means that the message triggered a Route. If you're seeing this, and the next log entry is prefixed with "Delivered", the message is likely being delivered to Gmail without issue. Check your Gmail spam folder if you still don't see the messages in the inbox folder.
Disclaimer: I work for Mailgun Support. :)

How can I send HTML email via Celery? It keeps sending in text/plain

I setup a system Django/Celery/Redis. And I used EmailMultiAlternatives to send my HTML and Text email.
When I send email as part of the request process, the email is sent in HTML. All runs well and it wraps around a function. Here's the code:
def send_email(email, email_context={}, subject_template='', body_text_template='',
body_html_template='', from_email=settings.DEFAULT_FROM_EMAIL):
# render content
subject = render_to_string([subject_template], context).replace('\n', ' ')
body_text = render_to_string([body_text_template], context)
body_html = render_to_string([body_html_template], context)
# send email
email = EmailMultiAlternatives(subject, body_text, from_email, [email])
email.attach_alternative(body_html, 'text/html')
email.send()
However, when I tried to run it as a Celery Task, like below, it just sent as "text/plain". What could be the problem? Or what can I do to find out more? Any hint or solution are greatly appreciated.
#task(name='tasks.email_features', ignore_result=True)
def email_features(user):
email.send_email(user.email,
email_context={'user': user},
subject_template='emails/features_subject.txt',
body_text_template='emails/features_body.txt',
body_html_template='emails/features_body.html')
Celery does not affect the executing results of tasks. Have you restarted celeryd after make change to the task? It's important for celery to reload the Python code.
When you were using EmailMultiAlternatives and email.attach_alternative(body_html, 'text/html'), the email was sent in the Content-Type: multipart/alternative; and the text/html is an alternative one, it depends on mail receipts to choose the content type of the mail during the rendering. So is the receipt same one between the view procedure and celery procedure?
You could output the sending mail directly, through python -m smtpd -n -c DebuggingServer localhost:25 to find out the actual messages. I've tested on my mac w/ redis-backed Celery, the outputs of the examples taken from the official doc are same as expected.
from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
class SendEmail(Task):
name="send_email"
def run(self,email):
subject = 'Daily News Letter'
html_message = render_to_string('letter.html', {'context': 'values'})
plain_message = strip_tags(html_message)
from_email = env('EMAIL_HOST_USER')
mail.send_mail(subject, plain_message, from_email, [email], html_message=html_message)
return None
send_email = celery_app.register_task(SendEmail())

Categories