Sending attachment from s3 to ses via lambda - amazon-s3

I am trying to send the attachment files that I read from S3 to SES mail from my lambda function. Attaching the code, the mail is being sent successfully but I am not receiving the emails, can someone please look if I am missing something?
I have not encountered any error, if I remove the attachment part of code the mail is received as expected.
import boto3
import json
import os
import requests
import io
import zipfile
from botocore.exceptions import ClientError
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import base64
# Create SQS, SES clients
sqs = boto3.client('sqs')
ses = boto3.client('ses')
s3 = boto3.client('s3')
def compose_email(recipients, sender, subject, body, attachment):
msg = MIMEMultipart()
msg.set_charset("utf-8")
msg['From'] = sender
msg['To'] = ", ".join(recipients)
msg['Subject'] = subject
msg.attach(MIMEText(body.encode("utf-8"), 'plain', 'UTF-8'))
if attachment:
part = MIMEBase('application', "octet-stream")
part.set_payload(attachment['data'])
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename=attachment['name'])
msg.attach(part)
return msg
def lambda_handler(event, context):
"""Sample Lambda function which reads from the SQS and fetch data from the API based on the api_url and body
received from SQS, uses API data to send emails.
"""
for record in event['Records']:
bucket_name = 'cvbucket'
data = {
"to_email": ["test#gmail.com"],
"body": "First email Test",
"subject": "Hey!",
"attachment_name": ["abc.pdf", "def.pdf"]
}
in_memory_zip = io.BytesIO()
with zipfile.ZipFile(in_memory_zip, mode='w') as zf:
for file_name in data["attachment_name"]:
# Read the file from S3
file = s3.get_object(Bucket=bucket_name, Key=file_name)
file_content = file['Body'].read()
# Add the file to the zip
zf.writestr(file_name, file_content)
in_memory_zip.seek(0)
zip_data = in_memory_zip.read()
recipients = data['to_email']
sender = os.environ['SES_SENDER_IDENTITY']
subject = data['subject']
body = data['body']
# Add the attachment to the email
attachment = {
'name': 'attachment.zip',
'data': base64.b64encode(zip_data).decode('utf-8')
}
message = compose_email(recipients, sender, subject, body, attachment)
try:
#Provide the contents of the email.
response = ses.send_raw_email(
Source=sender,
Destinations=recipients,
RawMessage={
'Data':message.as_string(),
},)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])

Related

Subscriptions was added in the Youtube AP's Activities: list recently?

I use this function (https://developers.google.com/youtube/v3/docs/activities/list) to retrieve list of user activities.
I use my channelId and I don't see subscriptions for period before autumn of 2021. Can anyone explain me why? May be you write me when this type of activity (subscription) was added in the type of request, named Activities: list?
Thanks!
See below example code:
import os
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
scopes = ["https://www.googleapis.com/auth/youtube.readonly"]
def main():
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
api_service_name = "youtube"
api_version = "v3"
client_secrets_file = "YOUR_CLIENT_SECRET_FILE.json"
# Get credentials and create an API client
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
credentials = flow.run_console()
youtube = googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials)
request = youtube.activities().list(
part="snippet,contentDetails",
channelId="yourChannelId", #Note: paste your own channelId
maxResults=300
)
response = request.execute()
print(response)
if __name__ == "__main__":
main()
You can do an example of request in the right side:
https://developers.google.com/youtube/v3/docs/activities/list

How to get messages of telegram channel by python-telegram-bot tool

I was wondering if there is a possible way to get messages from the telegram channel knowing that I logged in to this account and I am the admin of this channel so I just want the get messages.
import feedparser
from telegram import Update, ForceReply, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext, CallbackQueryHandler
from bs4 import BeautifulSoup
from datetime import datetime
import json
import telegram
from time import sleep
from telegram.ext import MessageHandler, Filters
class Config:
def __init__(self):
with open("config.json", "r") as config:
self.config = json.load(config)
class TelegramBotChannel:
def __init__(self, token, start_channel_id):
self.updater = Updater(token=token, use_context=True)
self.dispatcher = self.updater.dispatcher
self.start_channel_id = start_channel_id
if __name__ == '__main__':
telegram_bot = TelegramBotChannel(Config().config["token"], Config().config["start"])
pass
This is the minimal code to fetch the messages from a channel using a telegram bot which is the subscriber (only admin subscription possible) of the channel. Provide the correct bot api as KEY.:
from api_keys import bot_api_key as KEY
from telegram.ext import Updater, Filters, MessageHandler
updater = Updater(token=KEY, use_context=True)
dispatcher = updater.dispatcher
def forwarder(update, context):
msg = update.channel_post
if msg:
print(msg)
forwardHandler = MessageHandler(Filters.text & (~Filters.command), forwarder)
dispatcher.add_handler(forwardHandler)
updater.start_polling()
updater.idle()
Bots can only get updates about channel posts if they are a member in that channel (and bots can only be added to channels as admin). If they are admins in the channel, they will receive updates just like from every other chat.
Requirements :
Your bot should be in the channel. obviously as an admin
so first just make a function :
def forwader(update , context):
context.bot.copy_message("#temporary2for" ,"#tempmain" , update.channel_post.message_id)
After that make handler :
forwadHandler= MessageHandler(Filters.text & (~Filters.command) , forwader)
Than register your handler :
dispatcher.add_handler(forwadHandler)
Than don't forget to start Bot polling :
updater.start_polling()
updater.idle()
Full code :
from telegram import bot
from telegram.ext import Updater , CommandHandler , Filters , MessageHandler
from config import useless
import logging
updater = Updater(token=useless, use_context=True)
dispatcher = updater.dispatcher
import logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
def forwader(update , context):
context.bot.copy_message("#temporary2for" ,"#tempmain" , update.channel_post.message_id)
forwadHandler= MessageHandler(Filters.text & (~Filters.command) , forwader)
dispatcher.add_handler(forwadHandler)
updater.start_polling()
updater.idle()
Some Import are useless .

Facing "IllegalLocationConstraintException" error

I am trying to create a s3-bucket using AWS SDK for Python in PyCharm and facing the following error.
"An error occurred (IllegalLocationConstraintException) when calling the CreateBucket operation: The unspecified location constraint is incompatible for the region specific endpoint this request was sent to."
Here is my code:
import os
import boto3
from botocore.exceptions import ClientError
ACCESS_KEY = 'AWS_ACCESS_KEY_ID'
SECRET_KEY = 'AWS_SECRET_ACCESS_KEY'
PRI_BUCKET_NAME = 'soundcloud2'
TRANSIENT_BUCKET_NAME = 'soundcloud3'
def main():
"""entry point"""
access = os.getenv(ACCESS_KEY)
secret = os.getenv(SECRET_KEY)
s3 = boto3.resource('s3', aws_access_key_id=access, aws_secret_access_key=secret)
create_bucket(TRANSIENT_BUCKET_NAME, s3)
def create_bucket(name, s3):
try:
bucket = s3.create_bucket(Bucket=name)
except ClientError as ce:
print('error', ce)
if __name__ == '__main__':
main()
Try modifying your code as below:
bucket = s3.create_bucket(Bucket=name,
CreateBucketConfiguration={
'LocationConstraint': 'ap-south-1'}
)
or whatever region, unless your region is in the U.S.

AWS - Using email template from S3 bucket

I can send email with amazon SES in python with boto3. I made my email template and passing it as a parameter inside my code. I want to upload my email template in S3 bucket and intergrate it with my existing code. I have searched the documentation but can't find any lead. How do I do this? Here is my code so far:
import boto3
from botocore.exceptions import ClientError
SENDER = "************"
RECIPIENT = "*************"
AWS_REGION = "us-east-1"
SUBJECT = "Amazon SES Test (SDK for Python)"
BODY_TEXT = ("Amazon SES Test (Python)\r\n"
"This email was sent with Amazon SES using the "
"AWS SDK for Python (Boto)."
)
BODY_HTML = """<html>
<head></head>
<body>
<h1>Amazon SES Test (SDK for Python)</h1>
<p>This email was sent with
<a href='https://aws.amazon.com/ses/'>Amazon SES</a> using the
<a href='https://aws.amazon.com/sdk-for-python/'>
AWS SDK for Python (Boto)</a>.</p>
</body>
</html>
"""
CHARSET = "UTF-8"
client = boto3.client('ses',aws_access_key_id='**',
aws_secret_access_key='**',region_name='us-east-1')
s3_client = boto3.client('s3',aws_access_key_id='**',
aws_secret_access_key='***',region_name='us-east-1')
try:
#Provide the contents of the email.
response = client.send_email(
Destination={
'ToAddresses': [
RECIPIENT,
],
},
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML,
},
'Text': {
'Charset': CHARSET,
'Data': BODY_TEXT,
},
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT,
},
},
Source=SENDER,
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])
print(s3_client)
Basically I had to fetch the file from s3 as an object, which I did following this. I added these into my code:
s3_response_object = s3_client.get_object(Bucket='bucket name', Key='template.html')
object_content = s3_response_object['Body'].read()
BODY_HTML = object_content
You can create a template which will be stored in AWS and then you can use send_templated_email to use a template and render it , in case you want to customise it with variables.

How to transfert From Kraken to Poloniex by API

i would like to know can you transfert some currencies from Kraken to Poloniex using API functions ?
Didn't see anything talking about that.
Thank a lot
*
create new API key with "Withdraw funds" right on kraken
Go to account settings then click on "api" to go to settings api page, then click on "generate new key"
Fill all field and tick the box "Withdraw Funds", then validate.
add the poloniex deposit address in kraken (assuming deposit address already created)
Go to funding deposit page
then click on "withdraw" to go to funding withdraw page
Select the currency on the left side
(here we assume that you want withdraw BTC)
so you have to click on "Bitcoin (XBT)" on the left panel
Then click on "add address" then
fill both "Description" & "Bitcoin address" field.
Write down "Description" field because it will be required later when you will send API request to withdraw from Kraken to Poloniex.
Create the API request which will be sent to Kraken
Use the following code (re-use this example python library):
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import time
import requests
import urllib
import urllib2
import json
import hashlib
import httplib
import hmac
import random
import string
import base64
def _query( urlpath, req = {}, conn = None, headers = {}):
"""Low-level query handling.
Arguments:
urlpath -- API URL path sans host (string, no default)
req -- additional API request parameters (default: {})
conn -- kraken.Connection object (default: None)
headers -- HTTPS headers (default: {})
"""
uri = 'https://api.kraken.com'
url = uri + urlpath
if conn is None:
conn = Connection()
ret = conn._request(url, req, headers)
return json.loads(ret)
def query_private( method, req={}, conn = None):
#secret data
key = "123456789_my_api_key"
secret = "123456798_my_api_secret"
apiversion='0'
uri='https://api.kraken.com'
urlpath = '/' + apiversion + '/private/' + method
req['nonce'] = int(1000*time.time())
postdata = urllib.urlencode(req)
message = urlpath + hashlib.sha256(str(req['nonce']) +
postdata).digest()
signature = hmac.new(base64.b64decode(secret),
message, hashlib.sha512)
headers = {
'API-Key': key,
'API-Sign': base64.b64encode(signature.digest())
}
return _query(urlpath, req, conn, headers)
withdraw_params={
'asset': 'xbt',
'key': "Withdrawal address Description",
'amount': 0.25,
}
res=query_private('Withdraw', withdraw_params)
You'll need the withdrawFunds method from the Kraken API (https://www.kraken.com/help/api#withdraw-funds).
Using the Poloniex API, you'll need to get your deposit address using returnDepositAddresses. If you don't have a deposit address for the given cryptocurrency, use generateNewAddress.
Kraken API Documentation: https://www.kraken.com/help/api
Poloniex API Documentation: https://poloniex.com/support/api/