Can I rename an attachment of a received email via exchangelib? - python

I want to rename the attachments of some files I receive on an Exchange server. Is this possible?
What I've tried
from exchangelib import ServiceAccount, Configuration, Account, DELEGATE
from exchangelib import FileAttachment
from config import cfg
# Login
credentials = ServiceAccount(username=cfg['imap_user'],
password=cfg['imap_password'])
config = Configuration(server=cfg['imap_server'], credentials=credentials)
account = Account(primary_smtp_address=cfg['smtp_address'], config=config,
autodiscover=False, access_type=DELEGATE)
# Go through all emails, to find the example email
latest_mails = account.inbox.filter()
for msg in latest_mails:
for attachment in msg.attachments:
if attachment.name == 'numbers-test-document.pdf':
print("Rename the example attachment")
# does not work :-( - but no error either
attachment = FileAttachment(name='new-name.pdf',
content=attachment.content)
msg.attachments = [attachment]
msg.save()
print("#" * 80)
I don't get an error message. But it doesn't rename either. The code executes (I see Rename the example attachment), but it doesn't do so. How can this be done with exchangelib?

I have to take msg.detach and msg.attach
Complete working script
from exchangelib import ServiceAccount, Configuration, Account, DELEGATE
from exchangelib import FileAttachment
from config import cfg
def rename_attachment(msg, old_name, new_name):
"""
Rename an attachment `old_name` to `new_name`.
Parameters
----------
msg : Message object
old_name : str
new_name : str
Returns
-------
renames_executed : int
"""
renames_executed = 0
for attachment in msg.attachments:
if attachment.name == old_name:
renames_executed += 1
new_attachment = FileAttachment(name=new_name,
content=attachment.content)
msg.detach(attachment)
msg.attach(new_attachment)
msg.save()
return renames_executed
# Login
credentials = ServiceAccount(username=cfg['imap_user'],
password=cfg['imap_password'])
config = Configuration(server=cfg['imap_server'], credentials=credentials)
account = Account(primary_smtp_address=cfg['smtp_address'], config=config,
autodiscover=False, access_type=DELEGATE)
# Go through all emails, to find the example email
latest_mails = account.inbox.filter()
for msg in latest_mails:
rename_attachment(msg, 'numbers-test-document.pdf', 'new-name.pdf')
print("#" * 80)

Related

An element node 'soap:Envelope' of the type Element was expected, but node 's:envelope' of type Element was found

I get this with EWS when I try to get emails from my adresse.
This my code and it was working fine
from exchangelib import Account, Credentials, Configuration, Message, DELEGATE, Mailbox, FileAttachment, HTMLBody, FolderCollection
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter
from exchangelib.folders import Folder
import warnings
warnings.filterwarnings("ignore")
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter
credentials = Credentials(username='**domain\\XXXXXXXXXX**', password='**XXXXXXXXXXX**')
config = Configuration(server='**XXXXXXXXXXX**', credentials=credentials)
account = Account(primary_smtp_address='**XXXXXXXXXXX#COMPANY.COM**', config=config, autodiscover=False, access_type=DELEGATE)
for email in account.inbox.all().order_by('-datetime_received')[:8]:
print(str(email.subject))

Split message with media content and without Telegram pyrogram Bot

I have a script to copy and split messages from source to destination chats used pyrogram python library. Script should split messages bigger than 300 symbols on separated messages and he is doing it without any problems if there is no media content in the message. Messages with media content (photos, audios, videos) are just ignored and never get copied in destination chat any more.
Do someone has an idea how can i make script copy and split every message, no matter if there is a content or not and it is more than 300 symbols?
Code:
#!/usr/bin/env python3
from pyrogram import Client
from pyrogram import filters
# ~~~~~~ CONFIG ~~~~~~~~ #
ACCOUNT = "#account"
PHONE_NR = 'number'
API_ID = APIID
API_HASH = "APIHASH"
app = Client( ACCOUNT, phone_number=PHONE_NR, api_id=API_ID, api_hash=API_HASH )
### CHAT ID
# Variables
SOURCE_CHAT_TEST = chat_id
TARGET_CHAT_TEST = chat_id
# ~~~~~~~~~~~~~~~~~~~~~~ #
# Commands
#app.on_message(filters.text & filters.chat(SOURCE_CHAT_TEST))
def copy_to_channel(client, message):
if len(message.text) >= 300:
for i in range(0, len(message.text), 300):
client.send_message(
chat_id=TARGET_CHAT_TEST,
text=message.text[i:i+300])
else:
message.copy( chat_id=TARGET_CHAT_TEST )
app.run()
Try this to check for the existence of a text regardless message type:
#app.on_message(filters.chat(SOURCE_CHAT_TEST))
def copy_to_channel(client, message):
if message.text:
if len(message.text) >= 300:
for i in range(0, len(message.text), 300):
client.send_message(
chat_id=TARGET_CHAT_TEST,
text=message.text[i:i+300])
else:
message.copy( chat_id=TARGET_CHAT_TEST )
else:
pass

How to use dialogflow Client In Python

what i am trying is to get the response in python
import dialogflow
from google.api_core.exceptions import InvalidArgument
DIALOGFLOW_PROJECT_ID = 'imposing-fx-333333'
DIALOGFLOW_LANGUAGE_CODE = 'en'
GOOGLE_APPLICATION_CREDENTIALS = 'imposing-fx-333333-e6e3cb9e4adb.json'
text_to_be_analyzed = "Hi! I'm David and I'd like to eat some sushi, can you help me?"
session_client = dialogflow.SessionsClient()
session = session_client.session_path(DIALOGFLOW_PROJECT_ID, SESSION_ID)
text_input = dialogflow.types.TextInput(text=text_to_be_analyzed,
language_code=DIALOGFLOW_LANGUAGE_CODE)
query_input = dialogflow.types.QueryInput(text=text_input)
try:
response = session_client.detect_intent(session=session, query_input=query_input)
except InvalidArgument:
raise
print("Query text:", response.query_result.query_text)
print("Detected intent:", response.query_result.intent.display_name)
print("Detected intent confidence:", response.query_result.intent_detection_confidence)
print("Fulfillment text:", response.query_result.fulfillment_text)
And i am getting unable to verify credentials
google.auth.exceptions.DefaultCredentialsError: Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, please see https://cloud.google.com/docs/authentication/getting-started
This is my first question in stackoverflow :) i know i have done many
You need to export Service Account Key (JSON) file from your , and set an environment variable GOOGLE_APPLICATION_CREDENTIALS to the file path of the JSON file that contains your service account key. Then you can make call to dialogflow.
Steps to get Service Account Key:
Make sure you are using Dialogflow v2.
Go to general settings and click on your Service Account. This will redirect you to Google Cloud Platform project’s service account page.
Next step is to create a new key for the service account. Now create a service account and choose JSON as output key. Follow the instructions and a JSON file will be downloaded to your computer. This file will be used as GOOGLE_APPLICATION_CREDENTIALS.
Now in code,
import os
import dialogflow
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/path/to/file.json"
project_id = "your_project_id"
session_id = "your_session_id"
language_code = "en"
session_client = dialogflow.SessionsClient()
session = session_client.session_path(project_id, session_id)
text_input = dialogflow.types.TextInput(text=text, language_code=language_code)
query_input = dialogflow.types.QueryInput(text=text_input)
response_dialogflow = session_client.detect_intent(session=session, query_input=query_input)
This one works too in case you want to pick up the file from file system.
Recomended way is using env variables thoguh
import json
from google.cloud import dialogflow_v2
from google.oauth2 import *
session_client = None
dialogflow_key = None
creds_file = "/path/to/json/file.json"
dialogflow_key = json.load(open(creds_file))
credentials = (service_account.Credentials.from_service_account_info(dialogflow_key))
session_client = dialogflow_v2.SessionsClient(credentials=credentials)
print("it works : " + session_client.DEFAULT_ENDPOINT) if session_client is not None
else print("does not work")
I forgot to add the main article sorry...
Here it is :
https://googleapis.dev/python/google-auth/latest/user-guide.html#service-account-private-key-files

Cannot add file as inline attachment python flask using CID

I have spent hours searching for a solution to no avail. I am trying to include some images in automatically generated emails, and have come up against some problems. I Cannot include the actual url as gmail blocks the images totally, so I am trying to send as attachments and then use Cids to reference the attachments. The issue is I haven't found a way to do this. Any help would be ace.
I am running python 3.6 on with Apache2 on an Ubuntu server. I have tried encoding images in base64 but that didnt work at all. the images in the email simply didnt show up.
def createVoucher(email, expiry):
voucherId = str(uuid.uuid4())
email = email
value = 1
expiryDate = expiry
redeemed = 1
connection = mysql.get_db()
cursor = connection.cursor()
cursor.execute("INSERT INTO vouchers (VoucherID, Value, ExpiryDate, Redeemed, Email) VALUES (%s,%s,%s,%s,%s)", (voucherId, value, expiryDate, redeemed, email))
msgBody = render_template('admin/eVoucherEmail.html', voucherId=voucherId, expiry=expiry)
msg = Message('New Sunday Funday eVoucher Received', sender = MAIL_USERNAME, recipients = [email])
msg.html = msgBody
with app.open_resource("static/img/Facebook.jpg") as fp:
msg.attach("Facebook.jpg", "image/jpg", fp.read())
mail.send(msg)
connection.commit()
So the code posted works fine attaching the file, it's just assigning a content id that I can use where I am struggling.
Here's how I insert an inline jpg using flask_mail.
versions: python=3.7.6, flask=1.1.2, and flask-mail=0.9.1
The "disposition" in message.attach needs to be "inline", and the html for the img should contain "cid:my_cid" as the src.
import uuid
from flask import Flask
from flask_mail import Mail, Message
from pathlib import Path
app = Flask(__name__)
app.config.update(
MAIL_SERVER='smtp.gmail.com', MAIL_PORT=465, MAIL_USE_SSL=True,
MAIL_USERNAME="myfakeemail54858939#gmail.com", MAIL_PASSWORD="myfakepw54858939")
flask_mail = Mail(app)
def test_send_voucher():
to_addr = "myfakeemail54858939#gmail.com"
expiry = "29 February"
voucher_png_path = Path(__file__).parent / "static/Facebook.jpg"
sendVoucherEmail(app, to_addr, expiry, voucher_png_path)
def sendVoucherEmail(app: Flask, to_addr: str, expiry: str, voucher_png_path: Path):
voucher_id = str(uuid.uuid4())
html = f"""<html><head></head><body>
<p>Congratulations on your voucher!<br>Your voucher code is {voucher_id}.
The offer expires on {expiry}.<br>
<img src="cid:voucher_png" width=200>
</p></body></html>"""
with app.app_context():
mail = Mail(app)
message: Message = Message(subject="my subject", sender="myfakeemail54858939#gmail.com",
recipients=[to_addr], html=html)
with app.open_resource(voucher_png_path) as fp:
message.attach(filename="myfilename.png", content_type="image/png", data=fp.read(),
disposition="inline", headers=[['Content-ID', '<voucher_png>']])
mail.send(message)
This example successfully sent an email via gmail, with an inline image "Facebook.jpg," as in the original question.
screenshot of received email

Adding multiple recipents EWS API

I'm trying to send a simple email message to multiple recipients using EWS API via Python but I can't send to more than single address at a time.
import clr
clr.AddReferenceToFileAndPath("C:\\Microsoft\\Exchange\\Web Services\\2.1\\Microsoft.Exchange.WebServices.dll")
from Microsoft.Exchange.WebServices.Data import *
def main():
ex_service = ExchangeService(ExchangeVersion.Exchange2010)
ex_service.UseDefaultCredentials = True
ex_service.AutodiscoverUrl("me#companycom", redirect_url_validation_callback)
email = EmailMessage(ex_service)
email.ToRecipients.Add('r1#company.com')
email.Subject = "New TIP Report"
email.Body = '''A new TIP report has been published.
Please visit https://google.com and login to complete the form.'''
email.Send()
def redirect_url_validation_callback(redirect_url):
redirect_uri = Uri(redirect_url)
return redirect_uri.Scheme == "https"
if __name__ == "__main__":
main()
I read that I need to Mime Content properties, but I was not able to succeed. Any clue how to add multiple recipients using EWS API?
Just add a new line
email.ToRecipients.Add('r1#company.com')

Categories

Resources