The aim
To send custom text messages based on data read in from a csv file. Text messages should only be sent if the recipient is new or if previous messages to the recipient successfully delivered. If the phone number from the csv file is invalid for any reason, the program should just skip to the next number.
The problem
When deployed to Heroku, only the first exception is correctly handled. No messages are sent after the second invalid phone number is processed. However, it appears to work correctly if I run the program locally from the terminal.
The code
def send_sms(num, msg):
# sends message using Twilio's REST API
message = client.messages.create(
to=num,
from_=number,
body=msg,
status_callback=url)
def prep_msg(file):
# iterate through csv file containing phone numbers
for row in file:
msg = 'test message'
num = row[7]
# look for recipient in database of previously sent messages
record = Status.query.filter_by(to=num).first()
if record == None or record.status == 'delivered':
try:
send_sms(num, msg)
except Exception:
continue
return render_template('success.html')
The answer to this was to send the messages asynchronously as a background task using one of Heroku's worker dynos.
I used the following resources to research this:
https://devcenter.heroku.com/articles/python-rq
http://python-rq.org/docs/
Related
I am using telethon to automate some tasks on Telegram.
I am trying to create an API where third party users can provide phone number and enter code through an api. I have got the phone number part working, As I allow users to input their phone number through a webservice, this gets wrote to a file, then I am opening that file and fetching the phone number in python which is {number}, I then connect to the client using below.
client = TelegramClient(f'{number}', API_ID, API_KEY)
try:
await client.connect()
except Exception as e:
print('Failed to connect', e, file=sys.stderr)
return
Once the code is run the user enters the verification code (not in the python app) which gets wrote to a file.
And in python the following is returned
Please enter the code you received:
I can open the file which contains the verification code which as {code}
but how do I use {code} to reply to 'Please enter the code you received:'
Thanks
I think that you get the code on telegram and not in the file
It is possible, but this will be very complex as the code is sent to another device. You can write custom Telegram client that will send this code to your program, but it is too complex and in 99.9% of cases you won't need it.
Edit:
If you already have this code, let's say in code variable, you can try to use method sign_in() instead of connect()
try:
await client.sign_in(number, code)
except Exception as e:
print('Failed to connect', e, file=sys.stderr)
return
Reference for sign_in() in docs
I am using python 2.7 on ubuntu 16.04.
I have been using python to read emails out of mbox files on my pc which were created by thunderbird. I now want to add messages into those mbox files. I shut down thunderbird and then I try to run my python script from the command line. The python script does not give me any error messages at all, but I do not see any new messages being added into the mbox file when I open up thunderbird.
I did look to see if I have a permissions problem. I changed the permissions of the mbox file in linux to: view content=anyone, change content=anyone, execute=anyone.
I run my python script in sudo mode.
Here is my code which I have tried:
mboxfile = "/home/jan/.thunderbird/gkzlvipz.default/ImapMail/mail.jan.info/INBOX"
print("opening: "+mboxfile)
mbox = mailbox.mbox(mboxfile)
mbox.lock()
try:
print("Trying:Begins")
msg = mailbox.mboxMessage()
msg.set_unixfrom('author Sat Feb 7 01:05:34 2020')
msg['From'] = 'info#jan.info'
msg['To'] = 'ljan#gmail.com'
msg['Subject'] = 'JL Python Sample message 1'
msg.set_payload('This is the body.\nFrom (should be escaped).\nThere are 3 lines.\n')
mbox.add(msg)
mbox.flush()
print("Trying:Ends")
except Exception as e:
# Just print(e) is cleaner and more likely what you want,
# but if you insist on printing message specifically whenever possible...
Print("Exception - FAILED")
if hasattr(e, 'message'):
print("Error 1: " + e.message)
else:
print("Error 2: " + e)
finally:
print("Finally")
mbox.unlock()
sys.exit("PYTHON ENDS: TEST EMAIL SEND FINISHED")
The output I get when I run the above script is:
*** PYTESTTHUNDERBIRD BEGINS ***
opening: /home/jan/.thunderbird/gkzlvipz.default/ImapMail/mail.jan.info/INBOX
Trying:Begins
Trying:Ends
Finally
PYTHON ENDS: TEST EMAIL SEND FINISHED
I don't know what I'm doing wrong and why I am not getting any error messages.
I'll be most grateful for any help.
Thanks.
The messages you added to the mbox file aren't showing up in Thunderbird because you didn't update the index (.msf) file for that folder.
In Thunderbird, right-click on the folder name and select "Properties". In the "General Information" tab, read the blurb next to the "[Repair Folder]" button. Then click the folder. This will cause Thunderbird to rebuild the index from scratch — including the messages you've added. (Assuming of course you didn't mess them up in the process.)
Essentially I'm trying to create a very simple script that will send predesignated messages when a defined message is received. I'm new to Python.
What I have is basically this:
from skpy import Skype
sk = Skype("myskypeID", "pwd") # connect to Skype
content="the message i wanna send"
ch = sk.contacts["SkypeID_in_contacts"].chat
ch.sendMsg(content)
This will send a single message once to a designated account. How would I go about making it so that I can send specific messages to said account based on what messages I get from it?
I have a two part python standalone application: a publisher and a subscriber.
The publisher generates fake JSON devices objects and published them on a channel called "devices." And as you would guess, the subscriber subscribes to the channel "devices."
(Additionally, given optional command line arguments, the publisher or subscriber can write JSON objects to a socket or a local directory where an Apache Spark Streaming context pickups the JSON objects and processes it. For now, this is not in the picture, as it's optional.)
However, my problem is when my subscriber runs, after the publisher has finished, I get "ERROR: Forbidden".
Here are the respective python code snippets for the publisher:
pubnub = Pubnub(publish_key="my_key", subscribe_key="my_key")
....
pubnub.publish(ch, device_msg)
In the subscriber python file I have the following init code:
def receive(message, channel):
json.dumps(message)
def on_error(message):
print ("ERROR: " + str(message))
....
pubnub = Pubnub(publish_key="my_keys", subscribe_key="my_keys")
# subscribe to a channel and invoke the appropriate callback when a message arrives on that
# channel
#
pubnub.subscribe(channels=ch, callback=receive, error=on_error)
pubnub.start()
While the publisher, when run, seems to publish the JSON messages, all 120 in a loop, whereas the subscriber, when run, seems to fail with the following error message:
ERROR: Forbidden
My attempts to use "demo" keys have made no difference. Note that I'm using a trial account for PubNub.
Since this is one of my first app using its API, has anyone seen this problem before. Surely, something very obvious or trivial is amiss here.
Answer was that there was a copy/paste error with the pub/sub keys.
This little combination is processing the second to most recent email coming in - not the most recent.
Here's the filter:
# Exim filter
save /srv/domain.com/bin/mail 660
pipe "/srv/domain.com/bin/sendToMailChimp.py"
It works - i.e. I can see it saving to the mail file and it does call the script.. so great! So far so good..
Here's the script:
#!/usr/bin/python
MAILBOX_DIR = '/srv/domain.com/mailboxes/enqace/mail'
import mailbox
import logging
import time
time.sleep(10)
logging.basicConfig(filename='/srv/domain.com/mailboxes/enqace/logging.log',level=logging.DEBUG)
inbox = mailbox.mbox(MAILBOX_DIR)
logging.info('Script called')
for key in inbox.iterkeys():
logging.info(key)
message = inbox[key]
subject = message['subject']
logging.info(subject)
logging.info('===FINISH====')
(Prints 0-6 along with subject lines of each)
I can tail the log. It runs on getting an email - but seems to parse the mail mbox and completes before getting to the most recent email (i.e. the last one). It then hits the last one (the most recent) the next time an email comes in. So if there were 6 mails already in the mail file the new one - the 7th - subject line doesn't come up in the log entry. Only when an 8th comes in..
Is the script in effect running to quickly - like before exim has had a chance to send to the mail file? If so whats the work around? Adding a sleep(10) doesn't seem to do anything as seen above..
UPDATE:
By pulling up a python prompt I can see that python does get the correct amount of keys (i.e. message num) when called outside of the pipe
MAILBOX_DIR = 'mail'
import mailbox
inbox = mailbox.mbox(MAILBOX_DIR)
for key in inbox.iterkeys():
print key
(Prints 0-7)