I need to send mail to particular user from the database. i have data table where 1000 of records are available. each record have some email ids. or some id has assigned to multiple record . i need to send record to the particular email only.
I have form from where i used to select company name and strt date. from these i fetch all the value into list. now worries is how to send record to particular user
let my code example
def sendmail():
form = SQLFORM.factory(Field('select_company', db.company, represent=lambda c, row:get_company_name(c), requires = IS_IN_DB(db,'company.id','%(company)s')),
Field('choose_start_date','date',requires=IS_NOT_EMPTY(error_message='Please choose Start Date')),
Field('choose_end_date','date',requires=IS_NOT_EMPTY(error_message='Please choose end Date')))
if form.accepts(request,session):
session.company = form.vars.select_company
session.strtdate = form.vars.choose_start_date
session.enddate = form.vars.choose_end_date
mailidr()
return dict(form=form)
def mailidr():
from gluon.tools import Mail,datetime
mail=Mail()
#specify server
mail=auth.settings.mailer
mail.settings.server='smtp.gmail.com:587'
mail.settings.login='comdummy09#gmail.com:critical#009'
#specify address to send as
mail.settings.sender='comdummy09#gmail.com'
#send the message
list = []
for row in db((db.tracker.company == session.company) & (db.tracker.Complience_Status != 1) & (db.tracker.periodicity_due_date >= session.strtdate) & (db.tracker.periodicity_due_date <= session.enddate)).select():
list.append('<tr><td style="padding-top:5px;padding-bottom:5px;padding-right:5px;padding-left:5px;">'+row.Compliance_Area+'</td><td style="padding-top:5px;padding-bottom:5px;padding-right:5px;padding-left:5px;">'+row.law_description+'</td><td style="padding-top:5px;padding-bottom:5px;padding-right:5px;padding-left:5px;" >'''+row.activity_name+'''</td><td style="padding-top:5px;padding-bottom:5px;padding-right:5px;padding-left:5px;">'+str(row.periodicity_due_date)+'</td></tr>')
mail.send(to=[row.client_owner],
subject='Compliance and Due_Date',
message='<html>'
'<body>'
'<h1>Test Mails</h1>'
'<h2>Dear \t' +session.company+ '</h2>'
'</br><h3>REMINDER</h3>'
'<p>Please note that the fol1ing records are due between ' +session.strtdate+ ' to ' +session.enddate+ '</p>'
'<table border=1>'
'<thead >'
'<tr>'
'<th style="padding-top:5px;padding-bottom:5px;padding-right:5px;padding-left:5px;">Compliance Area</th>'
'<th>record</th><th>date (Due Date)</th>'
'</tr>'
'</thead>'
'<tbody>'
+str(list)+
'</tbody>'
'</table>'
'</body>'
'</html>')
response.flash='mail send'
return ''
from this code i a able to send mail. but problem is that user get n no mails
if i used to take mail.send to out side the function its not work
from the docs (http://www.web2py.com/books/default/chapter/29/08/emails-and-sms#Setting-up-email)
Mail returns True if it succeeds in sending the email and False
otherwise. A complete argument list for mail.send() is as follows:
So, for a test you should try capturing the response - e.g. change:
mail.send(to=[row.client_owner],
to
mail_response = mail.send(to=[row.client_owner],
and then return locals() instead of "" so you can see in a test page what (if any) failure you are getting in the send. this is just for testing...
A permanent alternate method is shows here: i am trying send email using web2py with gmail and using smtp setting i have attached all code
Related
I am using microsoft graph api to pull my emails in python and return them as a json object. There is a limitation that it only returns 12 emails. The code is:
def get_calendar_events(token):
graph_client = OAuth2Session(token=token)
# Configure query parameters to
# modify the results
query_params = {
#'$select': 'subject,organizer,start,end,location',
#'$orderby': 'createdDateTime DESC'
'$select': 'sender, subject',
'$skip': 0,
'$count': 'true'
}
# Send GET to /me/events
events = graph_client.get('{0}/me/messages'.format(graph_url), params=query_params)
events = events.json()
# Return the JSON result
return events
The response I get are twelve emails with subject and sender, and total count of my email.
Now I want iterate over emails changing the skip in query_params to get the next 12. Any method of how to iterate it using loops or recursion.
I'm thinking something along the lines of this:
def get_calendar_events(token):
graph_client = OAuth2Session(token=token)
# Configure query parameters to
# modify the results
json_list = []
ct = 0
while True:
query_params = {
#'$select': 'subject,organizer,start,end,location',
#'$orderby': 'createdDateTime DESC'
'$select': 'sender, subject',
'$skip': ct,
'$count': 'true'
}
# Send GET to /me/events
events = graph_client.get('{0}/me/messages'.format(graph_url), params=query_params)
events = events.json()
json_list.append(events)
ct += 12
# Return the JSON result
return json_list
May require some tweaking but essentially you're adding 12 to the offset each time as long as it doesn't return an error. Then it appends the json to a list and returns that.
If you know how many emails you have, you could also batch it that way.
I am using two slack API's, users.list() and users.getPresence(). I use users.list() to retrieve the user's names and IDs.
The users.getPresence() API takes the user ID as a parameter and only outputs their presence of 'active' or 'away' as it is shown here: https://api.slack.com/methods/users.getPresence
I tried taking the names I retrieved from users_list() and returning them along with the users_getPresence() API, but then I only got the list of names to repeat over each status.
client = slack.WebClient(API_KEY)
def users_list():
users_call = client.users_list()
users = users_call['members']
result = []
# loops for each user
for user in users:
uid = user['id']
name = user['profile']['real_name']
info = {"id": None, "name": None}
if users_call['ok']:
info['id'] = uid
info['name'] = name
result.append(info)
else:
return None
return result
def users_getPresence():
info = users_list()
users = []
for value in info:
uid = value['id']
users.append(uid)
presence = []
for user in users:
presence_call = client.users_getPresence(user = user)
if presence_call['ok']:
presence.append(presence_call['presence'])
else:
return None
return presence
Right now, the two API's have separate outputs, where users.list() returns ID and name while users.getPresence() returns presence.
How can I return the user's name and their status together?
Here is an updated version of your 2nd function that returns the list of all users with their presence status. Notice that I also added a sleep so you do not violate the rate limit of max 50 calls per minute.
def users_getPresence():
users = users_list()
for user in users:
presence_call = client.users_getPresence(user = user['id'])
sleep(1.2)
if presence_call['ok']:
user['presence'] = presence_call['presence']
else:
user['presence'] = None
return users
I also saw a couple of issues with your first function. Mainly checking for ok in the loop does not work, because if the method fails it will not contain any users and your script will fail before it reached the ok check.
I am making a program which imports an excel file with multiple vehicle registrations and the emails of people the vehicles belong to. The program searches the MOT database using the MOT API and extracts the days left on each vehicle's MOT. I have set a condition where if the days left are less than 30 the program will send an email to the person as reminder. At the moment, my program sends a generic email to everyone on the list whose MOT runs out in 30 days. I would like to personalise the email similar to this example:
"The MOT for your vehicle with registration _______ expires in __ days!"
So the program would take the registration and the days left from my dataframe and send it to the corresponding individual. I assume this will require some sort of a for loop but I am not sure how to implement it. Any help is much appreciated. Here is my code:
apiKey = 'abcdxyz'
import requests
from datetime import datetime
import smtplib
import time
import pandas as pd
import pprint as pp
import xlrd
df = pd.read_excel(r'vehicles.xlsx') # Reading the excel file with the vehicle database
registrations = df['registration'].tolist() # Converting the registrations column to a list
mobile = df['mobile'].tolist() # Converting the mobile numbers column to a list
email = df['email'].tolist() # Converting the email column to a list
list_days_left = [] # Empty list to store data later
# Function to extract days left on MOT using the given dataframe:
def check_days_left(regi):
headers = {
'Accept': 'application/json',
'x-api-key': apiKey,
}
params = (
('registration', regi),
)
response = requests.get('https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests',
headers=headers, params=params)
r = response.json() # This returns a list of dicts of the full MOT History data
carDetails = r[0] # Access the first dictionary of the list
motTests = carDetails['motTests'] # This returns a list of dicts again of the MOT tests
latestTest = motTests[0] # Access the first dictionary to get the details of the latest test
expDate = latestTest['expiryDate'] # This returns the expiry date key of the latest test dictionary
uk_date = datetime.strptime(expDate, '%Y.%m.%d') # Convert expDate to datetime format
difference = uk_date - datetime.now() # Gets the timedelta between now and expiry date
days_left = difference.days # Extract the number of days from the above as an int
return days_left
# Function to apply the above function to each registration in the dataframe and append it to the empty list creater earlier:
def get_days_left():
for reg in registrations:
list_days_left.append(check_days_left(reg))
# print(list_days_left)
df['days_left'] = list_days_left
# print(df)
df.drop(df[df.days_left > 30].index, axis=0, inplace=True)
print(df)
return df
# Function to send emails:
def send_mail(m):
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login('myemail#gmail.com', 'mypassword')
subject = 'Your MOT is expiring soon!'
body = f"The MOT for your vehicle is running out soon!"
msg = f'Subject: {subject}\n\n{body}'
server.sendmail(
'myemail#gmail.com',
m,
msg
)
print('EMAIL HAS BEEN SENT!')
server.quit()
# Calling the function to return a dataframe with just those vehicles whose MOT runs out in 30 days:
get_days_left()
# Calling the function to send email to each person on the list:
for mailid in df['email']:
send_mail(mailid)
In the get_days_left method, in the for loop you could get the days left from the check_days_left function and do a check there. As for the infomation such as their registration, you already have it because you're passing the registration to the check_days_left method.
def get_days_left():
for reg in registrations:
days_left = check_days_left(reg)
# Assuming days_left is an integer
if days_left < 30:
send_mail("ownersemail#email.com", reg=reg, days_left=days_left)
def send_mail(ownerEmail, reg, days_left):
# Send the mail here.
server.sendmail("me#mymail.com", ownerEmail, f"Your vehicle with registration: {reg} has {days_left} days left!")
I apologise for any formatting errors or if my response isn't top-notch, I haven't posted here before.
Edit: Added how send_mail could look for clarity.
for vehicle in r:
# do work
Inside the loop you'll access all the variables and send the mail.
I'm building a website using Django. And I want that users can be able to receive alerts via SMS when new topics are posted.
I tested textlocal but I had an issue when trying to send SMS to multiple numbers (numbers = ['xxxxx','xxxxx']) .(I don't want to use group_id).
Generally I want to be able to do something like this:
numbers = (SELECT number FROM users WHERE SMS_subscribe=1)
sender = 'mywebsite'
message = 'Hey, a new topic was posted'
send_sms(numbers, message, sender)
My textlocal test code:
#!/user/bin/python
# -*- coding: utf-8 -*-
from urllib2 import Request, urlopen
from urllib import urlencode
def send_sms(uname, hash_code, numbers, message, sender):
data = urlencode({
'username' : uname,
'hash' : hash_code,
'numbers' : numbers,
'message' : message,
'sender' : sender,
'test' : True
})
#data = data.encode('utf-8')
request = Request('https://api.txtlocal.com/send/?')
response = urlopen(request, data)
return response.read()
def just_one_sms_message(message, annonce_link, sender):
links_len=len(annonce_link) + len(sender) + 1
sms_max_len = 160 - links_len
if len(message)>sms_max_len:
message = message[:sms_max_len-6]+'... : '
else:
message += ' : '
return message + annonce_link + '\n' + sender
username = 'xxxxxxx#gmail.com'
hash_code = '3b5xxxxxxxxxxxxxxxxxxxxxxxxxxx8d83818'
numbers = ('2126xxxxx096','2126xxxxx888')
annonce_link = 'http://example.com/'
sender = 'sender'
message = 'New topics..'
message = just_one_sms_message(message, annonce_link, sender)
resp = send_sms(username, hash_code, numbers, message, sender)
print resp
Executing this code I get this error :
{"warnings":[{"code":3,"message":"Invalid number"}],"errors":[{"code":4,"message":"No recipients specified"}],"status":"failure"}
But if I change: numbers=('2126xxxxx096')it works.
What is the best way or web service to do this ?
There are a couple issues you're running into. The first is how tuple literals are defined.
('somenumber') is equivalent to 'somenumber' in python. It's just a string. The parentheses alone do not define a tuple literal. To define a single-element tuple literal, you need a trailing comma of the first element. E.G. ('somenumber',).
The second issue is how urlencode works. For each value in the data dictionary, it asks for the string representation.
In the case of ('2126xxxxx096','2126xxxxx888'), since it's evaluated as a tuple, it's encoded as ('2126xxxxx096','2126xxxxx888'), resulting in %28%272126xxxxx096%27%2C+%272126xxxxx888%27%29.
In the case of ('2126xxxxx096'), since it's evaluated as a string, it's encoded as 2126xxxxx096. Notice the lack of junk characters like %28 and %29.
So, in short, since the value of numbers in the urlencode dictionary is a tuple when you have multiple numbers, you need to convert the tuple into a comma-separated string. This can be accomplished via ",".join(numbers), which in the case of ('2126xxxxx096','2126xxxxx888') produces 2126xxxxx096%2C2126xxxxx888. With the fixed encoding, your message should now send to multiple numbers.
Iam working on a script to move mails from a imap server to gmail via imap.
I got it to copy the mails over and create the labels, but it sets the date to be now instead of to original date, when i look in gmail.
# fetch header of current mail form old server to get date
result, header = From.uid('fetch', num, '(BODY[HEADER.FIELDS (DATE SUBJECT)])')
headerdic = headerparser.parsestr(header[0][1])
# add dobble qoutes around date
date = '"' + headerdic["Date"] + '"'
# get mail content
result, data = From.uid('fetch', num, '(RFC822)')
mgs = data[0][1]
# append mail to server
To.append(folder_name, None, date, mgs)
I read in the in the documentation that the dobble qoutes was importat, but it didnt seams to do a difference.
update
I found that the following solution worked
result, header = From.uid('fetch', num, '(BODY[HEADER.FIELDS (DATE SUBJECT)])')
headerdic = headerparser.parsestr(header[0][1])
pz = email.utils.parsedate_tz(headerdic["Date"])
stamp = email.utils.mktime_tz(pz)
date = imaplib.Time2Internaldate(stamp)
result, data = From.uid('fetch', num, '(RFC822)')
mgs = data[0][1]
To.append(folder_name, None, date, mgs)
Its possible that i had the right solution earlier, but my mails was still in the trash in gmail, so it just reused a earlier test where i did not send the date.
Try escaping the quotes. date = '\"' + headerdic["Date"] + '\"'