From the below code, I am sending mail with some info.Here i need to get the message to my mail id,When he/she opens the mail.
How to do this in Python.
def Data(request):
templateName = "sendmail.html"
mapDictionary = {'fromMail': "xxxx.xxxx#gmail.com", 'password': "xxxxx", 'toMail': "yyyyy.yyyy#gmail.com#gmail.com",
"subject": "New Trip Confirmation", 'username': 'Ramesh','trip_start_date' : '2014-02-10',
'trip_start_place' : 'Visak', 'trip_start_time' : '11:00 AM', "templateName" : templateName
}
print ("call send mail from processNewTripData...")
return sendmail(request, mapDictionary)
def sendmail(request, mapDictionary):
try:
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()
server.login(mapDictionary["fromMail"],mapDictionary["password"])
context = Context(mapDictionary)
html_content = render_to_string(mapDictionary["templateName"], context)
#text_content = "This is Confirmation mail"
msg = MIMEText(html_content,'html')
msg['Subject'] = mapDictionary["subject"]
server.sendmail(mapDictionary["fromMail"], mapDictionary['toMail'], msg.as_string())
to_json = {'result' : "True"}
return HttpResponse(simplejson.dumps(to_json), content_type='application/json')
except Exception as e:
print str(e)
to_json = {'result' : "False"}
return HttpResponse(simplejson.dumps(to_json), content_type='application/json')
Have a try and add this header:
Disposition-Notification-To: "User" <user#user.com>
The reader may need to confirm that you get a reply. Also adding html content served by your server can be an option to recognize that the mail is read.
You should be able to do this with any of these lines
msg['Disposition-Notification-To'] = '"User" <user#user.com>'
msg['Disposition-Notification-To'] = 'user#user.com'
Related
I keep getting errors in the loading of the email data no email IDs found or no search results. Im using imaplib to login to a IMAP server from GMX.com looking for email subject that is UNSEEN and with Subject Alert: then trying to use that data extracted to execute trades on bybit API. So should I just change email librarys or modify the code somehow
` from flask import Flask, jsonify
import bybit
import re
import ssl
import certifi
import imaplib
class IMAPError(imaplib.IMAP4.error):
pass
app = Flask(__name__)
app.debug = True
#app.route('/e')
def execute_trade():
response = {}
HOST = "imap.gmx.com"
USERNAME = "example#gmx.com"
PASSWORD = "example"
try:
ssl_context = ssl.create_default_context(cafile=certifi.where())
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
with imaplib.IMAP4_SSL(HOST, 993, ssl_context=ssl_context) as imap:
imap.login(USERNAME, PASSWORD)
imap.select('INBOX',readonly=True)
mail_ids = imap.search(None, "UNSEEN", 'SUBJECT "Alert:"')[0].split()
print(mail_ids)
mail_ids = mail_ids[0].split()
valid_mail_ids = [mail_id for mail_id in mail_ids if mail_id.strip().isdigit()]
for mail_id in mail_ids:
try:
int(mail_id)
valid_mail_ids.append(mail_id)
except ValueError:
pass
if not valid_mail_ids:
response['error'] = "No valid email IDs found in the search results"
return response, 500
mail_id = valid_mail_ids[0]
email_data = imap.fetch(mail_id, "(RFC822)")
email_body = email_data[0][1].decode('utf-8')
account_side = re.search(r'Account side: (.*)', email_body)
if account_side:
response['account_side'] = account_side.group(1)
else:
response['error'] = "No account side information found in the email"
return response, 500
except (IMAPError, IndexError, UnicodeDecodeError, ssl.SSLError) as e:
response['error'] = f"Error accessing the email server: {str(e)}"
return response, 500
account_side = re.search(r'Account side: (.*)', email_body)
if account_side:
response['account_side'] = account_side = account_side.group(1)
else:
response['error'] = "No 'Account side' found in the email body"
return response, 500
order_price = re.search(r'Price: (.*)', email_body)
if order_price:
response['order_price'] = order_price = order_price
else:
response['error'] = "No 'Price' found in the email body"
return jsonify(response), 500
account_symbol = re.search(r'account_symbol: (.*)', email_body)
if account_symbol:
response['account_symbol'] = account_symbol = account_symbol.group(1)
else:
response['error'] = "No 'Account symbol' found in the email body"
return jsonify(response), 500
account_volume = re.search(r'account_volume: (.*)', email_body)
if account_volume:
response['account_volume'] = account_volume = account_volume.group(1)
else:
response['error'] = "No 'Account volume' found in the email body"
return jsonify(response), 500
imap.close()
imap.logout()
client = bybit.bybit(test=False, api_key="76QjbsflcrBdSZiSrU",api_secret="SGAAHPUfQnTm1d1EX12ffVaizjbFA4iT32ps")
if account_side and account_symbol and account_volume:
print(client.Order.Order_new(side=account_side, symbol=account_symbol, order_type="limit",qty=account_volume, price=order_price,time_in_force="gtc").result())
# Query Active Orders(real-time)
print(client.Order.Order_query(symbol='account_symbol').result())
# My Position
print(client.Positions.Positions_myPosition(
symbol=account_symbol).result())
if __name__ == '__main__':
app.run(port=5000)
``` `
I've tried changing the library to imapClient and other solutions like reading the email data differently but always the same errors
I tried adding
``` ` json_data = json.loads(email_body)
result = json_data.get('result')
if result:
response['result'] = result
else:
response['error'] = "No result information found in the email"
return response, 500
after the email body line still same error and importing json.
I have a flask application. I have written a loop which goes through a database and looks for users and based on some conditions sends emails to them.
for receiver in new_receivers:
user = User.query.filter_by(organization=receiver).first()
send_email(subject='You have new messages!',
sender='mail#mail.com',
recipient=user.email,
text_body= 'test',
html_body= 'test')
Sending email creates a new thread for sending email like this:
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(subject : str , sender : str , recipient : str , text_body='' , html_body='')->None:
msg = Message(subject, sender=sender, recipients=[recipient])
msg.body = text_body
msg.html = html_body
Thread(target=send_async_email, args=(app, msg)).start()
Is there a way to avoid creating hundreds of threads, but pass a list of emails to the thread and loop sending in here?
I collected messeges to list and passed them to thread, where send them in a loop.
emails = []
for receiver in new_receivers:
user = User.query.filter_by(organization=receiver).first()
emails.append(
{
"subject" : 'You have new messages!',
"sender" : 'mail#mail.com',
"recipient" : user.email,
"text_body" : 'test',
"html_body" : 'test'
}
)
meseges = []
for email in emails:
msg = Message(email["subject"], sender=email["sender"], recipients=email["sender"])
msg.body = email["text_body"]
msg.html = email["html_body"]
meseges.append(msg)
def send_async_email(app, msgs):
with app.app_context():
for msg in msgs:
mail.send(msg)
def send_messeges(messegs)->None:
Thread(target=send_async_email, args=(app, messegs)).start()
I'm trying to make an ajax request to will generate a password for a user and send them an email with the password. This all works fine, except for the error I'm getting at msg.send()
Ajax:
<script type="text/javascript">
var frm = $('#retrieveKeyForm');
frm.submit(function (e) {
e.preventDefault();
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
data: frm.serialize(),
success: function (data) {
console.log('Submission was successful.');
},
error: function (data) {
console.log('An error occurred.');
console.log(data);
},
});
});
</script>
Views.py
class GenerateSecretKey(APIView):
def get(self, request):
#Get email address from request
emailaddr = request.GET.get('email')
print(emailaddr)
#Show the email address(for debugging)
min_char = 10
max_char = 12
allchar = string.ascii_letters + string.digits
#Generate passsword
password = "".join(choice(allchar) for x in range(randint(min_char, max_char)))
print("Your password is {}".format(password))
subject, from_email, to = 'Your key is ready!', 'test#test.com', emailaddr
html_content = render_to_string('testapp/email.html', {'password':password})
text_content = strip_tags(html_content)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()
return Response({'Success':'Your key has been generated. Please check your email.'})
Error:
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
This block of code worked much better. I hadn't configured an SMTP server or specified any SMTP details so that's why I was getting that error. Special thanks to this guy https://github.com/llamafarmer/email/blob/master/sendEmailAttachment.py
fromaddr = "test#test.com"
toaddr = request.GET.get('email')
print(toaddr)
smtp_user = "test#gmail.com"
smtp_pass = "abctest"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "Ready!"
body = render_to_string('testapp/email.html', {'password':password})
msg.attach(MIMEText(body, 'html'))
server = smtplib.SMTP('in-v3.mailjet.com', 587)
server.starttls()
server.login(smtp_user, smtp_pass)
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
return Response({'Success':'Your key has been generated. Please check your email.'})
I have implemented Paypal integration in my Django app using Django-paypal
and along with that, I have setup signal receivers according to the documentation.
But the problem is: everytime when someone makes a payment it is flagged as duplicate even I'm passing a random invoice id along with paypal dictionary.
Here's what I have tried:
From views.py:
def generate_cid():
chars = "".join([random.choice(string.ascii_lowercase) for i in range(5)])
digits = "".join([random.choice(string.digits) for i in range(4)])
cid = digits + chars
return cid
def payment_process(request):
minutes = int(request.user.tagging.count()) * 5
testhours = minutes / 60
hours = ''
if request.user.tagging.count() > 11:
# hours = str(round(testhours, 3))
hours = 5
# invoice = generate_cid()
user_info = {
"name": str(request.user.first_name + ' ' + request.user.last_name),
"hours": str(hours),
"taggedArticles": str(request.user.tagging.count()),
"email": str(request.user.email),
"date": str(datetime.date.today()),
}
paypal_dict = {
"business": settings.PAYPAL_RECEIVER_EMAIL,
"item_name": "Certificate of Completion",
"custom": json.dumps(user_info),
"invoice": str(generate_cid()),
"amount": "95.00",
"currency_code": "USD",
"notify_url": settings.host + '/users/paypal',
"return_url": settings.host + "/users/done/",
"cancel_return": settings.host + "/users/cancel/",
}
# Create the instance.
form = PayPalPaymentsForm(initial=paypal_dict)
context = {"form": form}
return render(request, "users/generateCert.html", context)
From signals.py:
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
# Undertake some action depending upon `ipn_obj`.
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment is completed')
user_infor = ast.literal_eval(ipn_obj.custom)
if ipn_obj.receiver_email == settings.PAYPAL_RECEIVER_EMAIL:
print('And Payment is valid')
# generate and send an email with pdf certificate file to the user's email
user_infor = ast.literal_eval(ipn_obj.custom)
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
"date": user_infor['date'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
#receiver(invalid_ipn_received)
def do_not_show_me_the_money(sender, **kwargs):
print('And Payment is not valid')
ipn_obj = sender
user_infor = ast.literal_eval(ipn_obj.custom)
to_emails = [str(user_infor['email'])]
subject = "Certificate"
# message = 'Enjoy your certificate.'
email = EmailMessage(subject, body='Unfortunately, there\'s something wrong with your payment.Check your'
+ 'paypal account, please!',
from_email=settings.EMAIL_HOST_USER, to=to_emails)
# email.content_subtype = "pdf" # Main content is now text/html
# email.encoding = 'us-ascii'
email.send()
valid_ipn_received.connect(show_me_the_money)
Actually, I'm receiving both (Success & Fail) signals with a short difference of time(approx 2 min) for a single transaction.
And below is the screenshot for how IPNs received in Django admin:
Also, From the console:
In the signals.py both valid and invalid IPN received called, that's why it returns invalid IPN before sending the email.
Here is the correct and working signals.py:
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
# Undertake some action depending upon `ipn_obj`.
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment is completed')
user_infor = ast.literal_eval(ipn_obj.custom)
if ipn_obj.receiver_email == settings.PAYPAL_RECEIVER_EMAIL:
print('And Payment is valid')
# generate and send an email with pdf certificate file to the user's email
user_infor = ast.literal_eval(ipn_obj.custom)
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
"date": user_infor['date'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
else:
payment_was_flagged.connect(do_not_show_me_the_money)
def do_not_show_me_the_money(sender, **kwargs):
print('And Payment is not valid')
ipn_obj = sender
user_infor = ast.literal_eval(ipn_obj.custom)
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
# message = 'Enjoy your certificate.'
email = EmailMessage(subject, body='Unfortunately, there\'s something wrong with your payment as it\'s'
'not validated.Check your PayPal account, please!',
from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.send()
valid_ipn_received.connect(show_me_the_money)
Just need to call invalid_ipn only in case of an invalid payment.
Im triying to send a mass email with django's "send_mass_email" method, i've read the documentation but the examples only show plain text messages.
How can i be able to send HTML messages with the "send_mass_emal" method? i tried like a regular email but the recived only html code. Here is my code:
for row_index in range(12, sheet.nrows):
if sheet.cell(rowx=row_index, colx=0).value != "":
template = get_template("MonthlyEmail.html")
context = Context({
'name': str(clean_string(sheet.cell(rowx=row_index, colx=2).value)),
'doc_type': str(sheet.cell(rowx=row_index, colx=4).value),
'document': str(sheet.cell(rowx=row_index, colx=3).value),
'email': str(sheet.cell(rowx=row_index, colx=5).value),
'acc_numb': str(sheet.cell(rowx=row_index, colx=6).value),
'brute_salary': str(sheet.cell(rowx=row_index, colx=8).value),
'vacation_commision': str(sheet.cell(rowx=row_index, colx=9).value),
'brute_total': str(sheet.cell(rowx=row_index, colx=10).value),
'social_sec': str(sheet.cell(rowx=row_index, colx=14).value),
'isr': str(sheet.cell(rowx=row_index, colx=27).value),
'other_retention': str(sheet.cell(rowx=row_index, colx=13).value),
'net_payment': str(sheet.cell(rowx=row_index, colx=29).value)
})
content = template.render(context)
messages.append(('Monthly Salary Report', content,
'intranet#intranet.com',
[str(sheet.cell(rowx=row_index, colx=5).value)]))
send_mass_mail_html(messages, fail_silently=False)
It does not look like send_mass_email() supports HTML emails. But there is a way to do it by taking inspiration from the code of Django's send_mail() function:
connection = connection or get_connection(
username=auth_user,
password=auth_password,
fail_silently=fail_silently,
)
mail = EmailMultiAlternatives(subject, message, from_email, recipient_list, connection=connection)
if html_message:
mail.attach_alternative(html_message, 'text/html')
mail.send()
The general strategy seems to create a connection first, then for each email you need to send, create an instance of EmailMultiAlternatives, passing it the existing connection, then send it, exactly as send_mail but in a loop...
I have wrote my own functionality to use mass email by using the django documentaion as reference.
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
def get_rendered_html(template_name, context={}):
html_content = render_to_string(template_name, context)
return html_content
def send_email(subject, html_content, text_content=None, from_email=None, recipients=[], attachments=[], bcc=[], cc=[]):
# send email to user with attachment
if not from_email:
from_email = settings.DEFAULT_FROM_EMAIL
if not text_content:
text_content = ''
email = EmailMultiAlternatives(
subject, text_content, from_email, recipients, bcc=bcc, cc=cc
)
email.attach_alternative(html_content, "text/html")
for attachment in attachments:
# Example: email.attach('design.png', img_data, 'image/png')
email.attach(*attachment)
email.send()
def send_mass_mail(data_list):
for data in data_list:
template = data.pop('template')
context = data.pop('context')
html_content = get_rendered_html(template, context)
data.update({'html_content': html_content})
send_email(**data)
message1 = {
'subject': 'Subject here',
'text_content': 'Here is the message',
'from_email': 'from#example.com',
'recipients': ['first#example.com', 'other#example.com'],
'template': "template1.html",
'context': {"d1": "mydata"}
}
message2 = {
'subject': 'Subject here',
'text_content': 'Here is the message',
'from_email': 'from#example.com',
'recipients': ['first#example.com', 'other#example.com'],
'template': "template2.html",
'context': {"d2": "mydata"}
}
send_mass_mail([message1, message2])
Reference: https://docs.djangoproject.com/en/1.11/_modules/django/core/mail/#send_mass_mail
I wrote custom mass mail method and it is working fine:-
from django.core.mail.message import EmailMessage
from django.core.mail import get_connection
def send_custom_mass_mail(datatuple, fail_silently=False, auth_user=None,
auth_password=None, connection=None):
"""
coloned fromt he core
"""
connection = connection or get_connection(
username=auth_user,
password=auth_password,
fail_silently=fail_silently,
)
EmailMessage.content_subtype = 'html'
messages = [
EmailMessage(subject, message, sender, recipient, connection=connection)
for subject, message, sender, recipient in datatuple
]
return connection.send_messages(messages)
Then I use as per document:
send_custom_mass_mail((mail_to_lead), fail_silently=False)