Trying to send emails with Gmail API - python-3.x

I've been followning tutorials and reading articles trying to learn how to make sense of the gmail API using python 3.
I've gotten stuck on the messages.send method.
My authentication works but my CreateMessage function is throwing an error.
Here is my code so far:
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_bytes())}
message = CreateMessage('xxxxxxxx#gmail.com','xxxxxxxx#gmail.com','subject','message text')
service = build('gmail', 'v1', credentials=creds)
created_message = service.users().messages().send(userId='me', body=message).execute()
The error it's throwing is "TypeError: Object of type bytes is not JSON serializable"
Any and all contrusctive criticism is welcome. Or any quality tutorials on the subject you can direct me to! Thank you.

base64.urlsafe_b64encode returns a bytes object. You should convert this to a string with .decode("utf-8"), which should fix your error.

Related

Add a photo to an existing message python telebot

For example, I have an existing message created by
bot.send_message(message.chat_id, "Hello, world!")
Then I changed it in callback_query_handler as follows
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Hello, Stackoverflow!", reply_markup=tutors_markup, parse_mode = 'Markdown')
After that I do some manipulations. And then I need to add a photo to the message with "Hello, Stackoverflow!".
How can i do it?
(I use telebot library)
I was trying to edit by
photo = open(f'photo_{result[0]}.jpg', 'rb')
bot.edit_message_media(media=telebot.types.InputMedia(type='photo', media=photo, caption = "noitpac"), chat_id=call.message.chat.id, message_id=call.message.message_id)
But got
telebot.apihelper.ApiTelegramException: A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: there is no media in the message to edit
And I understand this error, but don't what to do.

How would I save a file received by discord.py

I was working on my discord bot trying to implement a email feature where you imbed a file and then the discord bot downloads it and sends it back out to the server. I came across the issue where I have no idea how I would begin to save the file. You can find my code at https://github.com/Omar-Alabdalla/DiscordBot. the specific files that have the emailing feature are mailFunctions(discord commands part) and basicMail(email commands part).
I looked through the docs of nextcord.py and couldn't find any simple way that I could understand. I probably just missed what I was supposed to find though.
discord command Code:
#commands.command()
async def mailFile(self, ctx, *stuff):
# received if else statement from stackoverflow: https://stackoverflow.com/questions/65169339/download-csv-file-sent-by-user-discord-py
if str(ctx.attachments) == "[]": # This checks if there is an attachment on the message
return "You didn't include a file"
else:
await save("mailFile
The mailing class code:
def sendFileMail(rmail, message):
mail_content = '''Hello,
This is a test mail.
In this mail we are sending some attachments.
The mail is sent using Python SMTP library.
Thank You
'''
# Setup the MIME
message = MIMEMultipart()
message['From'] = sender_email
message['To'] = rmail
message['Subject'] = 'A test mail sent by Python. It has an attachment.'
# The subject line
# The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
attach_file_name = 'TP_python_prev.pdf'
attach_file = open(attach_file_name, 'rb') # Open the file as binary mode
payload = MIMEBase('application', 'octate-stream')
payload.set_payload(attach_file.read())
encoders.encode_base64(payload) # encode the attachment
# add payload header with filename
payload.add_header('Content-Decomposition', 'attachment', filename=attach_file_name)
message.attach(payload)
# Create SMTP session for sending the mail
session = smtplib.SMTP('smtp.gmail.com', 587) # use gmail with port
session.starttls() # enable security
session.login(sender_email, password) # login with mail_id and password
text = message.as_string()
session.sendmail(sender_email, rmail, text)
session.quit()
print('Mail Sent')
Apologies for not including code prior First time posting on stack overflow
See Attachment.save: https://nextcord.readthedocs.io/en/latest/api.html?highlight=attachment#nextcord.Attachment.save
for attachment in ctx.message.attachments:
await attachment.save(attachment.filename)

Twilio WhatsApp bug

I am getting this unexpected error with no explanation regarding Twilio API for WhatsApp messaging:-
print("Please enter a message.")
body_of_the_message = input()
account_sid = mysid
auth_token = myauthtoken
client = Client(account_sid, auth_token)
message = client.messages.create(from_='whatsapp:mytwilionum', body=(body_of_the_message),to='whatsapp:+myphone' )
sid = message.sid
print(f"The message SID is:- {sid}")
When I run this, I pass in “Hi there.” for the input.
This is what I get in response:-
The message SID is:- (sid)
I don’t see any notifications for the message being sent, and even when I check the chat history. Please help me with this stuff.

With the Azure ServiceBus 7.0 SDK, how do I get a reference to a ServiceBusClient using a ServiceBusManagementClient class?

I'm using the latest Python Azure SDK
azure-mgmt-servicebus==6.0.0
azure-servicebus==7.0.0
I get a reference to a ServiceBusManagementClient like so ...
def _get_sb_client(self):
credential = ClientSecretCredential(
tenant_id=self._tenant,
client_id=self._client_id,
client_secret=self._client_secret
)
return ServiceBusManagementClient(
credential, self._subscription)
However, according to this -- https://learn.microsoft.com/en-us/python/api/overview/azure/servicebus?view=azure-python#service-bus-topics-and-subscriptions, in order to send a message on a topic,
topic_client = sb_client.get_topic("MyTopic")
I need a reference to a azure.servicebus.ServiceBusClient object. However, the docs don't give any explanations about how to generate such an instance, other than through a connection string, which we are not using. How can I get an instance of ServiceBusClient using ClientSecretCredential or ServiceBusManagementClient instances?
I'd respond with few things, do let me know if any of this needs clarification or is off-base:
The doc you linked is not for 7.0.0, but for 0.50.3, which might explain some of the confusion. I would advise using the docs rooted in the readme for which one of the comparable docs to the one you referenced is here. (The process of replacing the historical docs is a known issue and being addressed, full disclosure speaking as a maintainer of the python SDK component)
I would call out that you initialized a ServiceBusManagementClient (which would be used for creating/deleting topics) and not the ServiceBusClient (which would be used for sending and receiving.) kindly see the document I listed above for an example of how to send to the topic. I'll paste a comprehensive example from that link at the bottom of this post for posterity in case anything shifts in the future, that this post is still relevant for version 7.0.0
For authenticating using an Azure Identity credential, I would point you at the documentation in the readme here and the sample linked therein, and pasted below.
Example of sending and receiving to a topic/subscription
from azure.servicebus import ServiceBusClient, ServiceBusMessage
CONNECTION_STR = "<NAMESPACE CONNECTION STRING>"
TOPIC_NAME = "<TOPIC NAME>"
SUBSCRIPTION_NAME = "<SUBSCRIPTION NAME>"
def send_single_message(sender):
message = ServiceBusMessage("Single Message")
sender.send_messages(message)
print("Sent a single message")
def send_a_list_of_messages(sender):
messages = [ServiceBusMessage("Message in list") for _ in range(5)]
sender.send_messages(messages)
print("Sent a list of 5 messages")
def send_batch_message(sender):
batch_message = sender.create_message_batch()
for _ in range(10):
try:
batch_message.add_message(ServiceBusMessage("Message inside a ServiceBusMessageBatch"))
except ValueError:
# ServiceBusMessageBatch object reaches max_size.
# New ServiceBusMessageBatch object can be created here to send more data.
break
sender.send_messages(batch_message)
print("Sent a batch of 10 messages")
servicebus_client = ServiceBusClient.from_connection_string(conn_str=CONNECTION_STR, logging_enable=True)
with servicebus_client:
sender = servicebus_client.get_topic_sender(topic_name=TOPIC_NAME)
with sender:
send_single_message(sender)
send_a_list_of_messages(sender)
send_batch_message(sender)
print("Done sending messages")
print("-----------------------")
with servicebus_client:
receiver = servicebus_client.get_subscription_receiver(topic_name=TOPIC_NAME, subscription_name=SUBSCRIPTION_NAME, max_wait_time=5)
with receiver:
for msg in receiver:
print("Received: " + str(msg))
receiver.complete_message(msg)
Example of authenticating with Azure Identity
import os
from azure.servicebus import ServiceBusClient, ServiceBusMessage
from azure.identity import EnvironmentCredential
FULLY_QUALIFIED_NAMESPACE = os.environ['SERVICE_BUS_NAMESPACE']
QUEUE_NAME = os.environ["SERVICE_BUS_QUEUE_NAME"]
credential = EnvironmentCredential()
servicebus_client = ServiceBusClient(FULLY_QUALIFIED_NAMESPACE, credential)
with servicebus_client:
sender = servicebus_client.get_queue_sender(queue_name=QUEUE_NAME)
with sender:
sender.send_messages(ServiceBusMessage('Single Message'))

send message from bot to direct message after typing /slash command

I'm trying to make SlackBot and if I call him in some public channel it works fine but when I call him (type slash-command) in any direct channel I receive "The server responded with: {'ok': False, 'error': 'channel_not_found'}". In public channels where I've invited my bot it works fine, but if I type "/my-command" in any DM-channel I receive response in separate DM-channel with my bot. I expect to receive these responses in that DM-channel where I type the command.
Here is some part of my code:
if slack_command("/command"):
self.open_quick_actions_message(user_id, channel_id)
return Response(status=status.HTTP_200_OK)
def open_quick_actions_message(self, user, channel):
"""
Opens message with quick actions.
"""
slack_template = ActionsMessage()
message = slack_template.get_quick_actions_payload(user=user)
client.chat_postEphemeral(channel=channel, user=user, **message)
Here are my Event Eubscriptions
Here are my Bot Token Scopes
Can anybody help me to solve this?
I've already solved my problem. Maybe it will help someone in the future. I've sent my payload as the immediate response as it was shown in the docs and the response_type by default is set to ephemeral.
The part of my code looks like this now:
if slack_command("/command"):
res = self.slack_template.get_quick_actions_payload(user_id)
return Response(data=res, status=status.HTTP_200_OK)
else:
res = {"text": "Sorry, slash command didn't match. Please try again."}
return Response(data=res, status=status.HTTP_200_OK)
Also I have an action-button and there I need to receive some response too. For this I used the response_url, here are the docs, and the requests library.
Part of this code is here:
if action.get("action_id", None) == "personal_settings_action":
self.open_personal_settings_message(response_url)
def open_personal_settings_message(self, response_url):
"""
Opens message with personal settings.
"""
message = self.slack_template.get_personal_settings_payload()
response = requests.post(f"{response_url}", data=json.dumps(message))
try:
response.raise_for_status()
except Exception as e:
log.error(f"personal settings message error: {e}")
P. S. It was my first question and first answer on StackOverflow, so don't judge me harshly.

Resources