From 3c379a9bf256e6ec66d737f21f8c9a9a11730cf1 Mon Sep 17 00:00:00 2001 From: Vikas Nale Date: Fri, 19 Sep 2025 18:11:31 +0530 Subject: [PATCH 1/3] version 1 --- mailling/mail-templates/charts.html | 157 +++++ mailling/mail-templates/dpr.html | 598 +++++++++++++++++ mailling/test mail sender/body.txt | 157 +++++ python-email-sender/body.txt | 599 ++++++++++++++++++ python-email-sender/config.json | 10 + .../mail-sender-with-charts.py | 84 +++ .../test-mail-sender-body-file.py | 35 + python-email-sender/test-mail-sender.py | 84 +++ 8 files changed, 1724 insertions(+) create mode 100644 mailling/mail-templates/charts.html create mode 100644 mailling/mail-templates/dpr.html create mode 100644 mailling/test mail sender/body.txt create mode 100644 python-email-sender/body.txt create mode 100644 python-email-sender/config.json create mode 100644 python-email-sender/mail-sender-with-charts.py create mode 100644 python-email-sender/test-mail-sender-body-file.py create mode 100644 python-email-sender/test-mail-sender.py diff --git a/mailling/mail-templates/charts.html b/mailling/mail-templates/charts.html new file mode 100644 index 0000000..5d035d0 --- /dev/null +++ b/mailling/mail-templates/charts.html @@ -0,0 +1,157 @@ + + + + + + CSS Donut Variants + + + +
+ +
+ 45% +
+ + +
+ 73% +
+ + +
+ 90% +
+ +
+
+
+
25%
+
+ +
+
50%
+
+ +
+
75%
+
+ +
+
90%
+
+
+ + + diff --git a/mailling/mail-templates/dpr.html b/mailling/mail-templates/dpr.html new file mode 100644 index 0000000..d94e57d --- /dev/null +++ b/mailling/mail-templates/dpr.html @@ -0,0 +1,598 @@ + + + + + + Daily Progress Report + + + + +
+ +
+

Daily Progress Report

+
+ Project: ANP ultimas wakad
+ Date: 17 September 2025 +
+
+ + +
+ * Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC +
+ + +
+
+

TODAY'S ATTENDANCE

+
+ + +
+ +
+ 20 / 30 +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+ +
+

DAILY TASKS COMPLETED

+
+ + +
+ +
+ 20 / 30 +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+

DAILY TASKS COMPLETED

+

20 / 30

+

Team member present

+
+
Completed
+
In Progress
+
Pending
+
+
+ +
+

PROJECT COMPLETION STATUS

+

20 / 30

+

Team member present

+
+
Completed
+
In Progress
+
Pending
+
+
+ +
+

Regularization Pending

+

28/32

+

Regularization Pending

+
+
Completed
+
In Progress
+
Pending
+
+
+ +
+ +
+

Checkout Pending

+
+ + +
+ + +
+ +
+ 73% +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+ + +
+
+

Team members present on the site

+
+
+
+
+
+

Activity Report Pending

+
+
+ + +
+ +
+ 73% +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+ +
+

Team Strength on Site

+
+ + + + + + + + + + + + + + + + + + + + + +
Site Engineer1
Weilder15
Helper2
Painter1
+
+
+ + +
+

Activities (Tasks) Performed 17-Sep-2025

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NAMEJOB ROLECHECK INCHECK OUT
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
+
+ + + +
+ You have received this email because it contains important information about your Marco PMS Account account. +
+
+ + + \ No newline at end of file diff --git a/mailling/test mail sender/body.txt b/mailling/test mail sender/body.txt new file mode 100644 index 0000000..5d035d0 --- /dev/null +++ b/mailling/test mail sender/body.txt @@ -0,0 +1,157 @@ + + + + + + CSS Donut Variants + + + +
+ +
+ 45% +
+ + +
+ 73% +
+ + +
+ 90% +
+ +
+
+
+
25%
+
+ +
+
50%
+
+ +
+
75%
+
+ +
+
90%
+
+
+ + + diff --git a/python-email-sender/body.txt b/python-email-sender/body.txt new file mode 100644 index 0000000..67787e4 --- /dev/null +++ b/python-email-sender/body.txt @@ -0,0 +1,599 @@ + + + + + + Daily Progress Report + + + + +
+ +
+

Daily Progress Report

+
+ Project: ANP ultimas wakad
+ Date: 17 September 2025 +
+
+ + +
+ * Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC +
+ + +
+
+

TODAY'S ATTENDANCE

+
+ + +
+ +
+ 20 / 30 +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+ +
+

DAILY TASKS COMPLETED

+
+ + +
+ +
+ 20 / 30 +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+

DAILY TASKS COMPLETED

+

20 / 30

+

Team member present

+ +
+
Completed
+
In Progress
+
Pending
+
+
+ +
+

PROJECT COMPLETION STATUS

+

20 / 30

+

Team member present

+
+
Completed
+
In Progress
+
Pending
+
+
+ +
+

Regularization Pending

+

28/32

+

Regularization Pending

+
+
Completed
+
In Progress
+
Pending
+
+
+ +
+ +
+

Checkout Pending

+
+ + +
+ + +
+ +
+ 73% +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+ + +
+
+

Team members present on the site

+
+
+
+
+
+

Activity Report Pending

+
+
+ + +
+ +
+ 73% +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+ +
+

Team Strength on Site

+
+ + + + + + + + + + + + + + + + + + + + + +
Site Engineer1
Weilder15
Helper2
Painter1
+
+
+ + +
+

Activities (Tasks) Performed 17-Sep-2025

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NAMEJOB ROLECHECK INCHECK OUT
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
+
+ + + +
+ You have received this email because it contains important information about your Marco PMS Account account. +
+
+ + + \ No newline at end of file diff --git a/python-email-sender/config.json b/python-email-sender/config.json new file mode 100644 index 0000000..b978fa3 --- /dev/null +++ b/python-email-sender/config.json @@ -0,0 +1,10 @@ +{ + "EMAIL_CONFIGURATION": { + "EMAIL_HOST": "mail.marcoaiot.com", + "EMAIL_PORT": 587, + "EMAIL_USER": "admin@marcoaiot.com", + "EMAIL_PASS": "xxx", + "EMAIL_SUBJECT": "Database backup process", + "EMAIL_RECEIVERS": "vikas@marcoaiot.com,umesh@marcoaiot.com" + } +} \ No newline at end of file diff --git a/python-email-sender/mail-sender-with-charts.py b/python-email-sender/mail-sender-with-charts.py new file mode 100644 index 0000000..b0c168b --- /dev/null +++ b/python-email-sender/mail-sender-with-charts.py @@ -0,0 +1,84 @@ +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from email.mime.image import MIMEImage +import os +import cairosvg + +def generate_donut_svg(percentage, color="#0d6efd", size=120, thickness=4): + """ + Generate an inline SVG donut chart. + """ + svg = f""" + + + + + + + {percentage}% + + """ + return svg + +# Sender and receiver +sender_email = "marcoioitsoft@gmail.com" +receiver_emails = ["vikasnale@gmail.com", "vikas@marcoaiot.com", "umeshvdesai@outlook.com"] +password = "qrtq wfuj hwpp fhqr" # Use Gmail App Password here + +# Read HTML body from file +file_path = os.path.join(os.path.dirname(__file__), "body.txt") +with open(file_path, "r", encoding="utf-8") as f: + body = f.read() + +# Create the email +message = MIMEMultipart("related") +message["From"] = sender_email +message["To"] = ", ".join(receiver_emails) +message["Subject"] = "Test HTML Email with Donut Charts" + +# Generate SVGs and convert to PNGs +donut_svgs = [ + generate_donut_svg(45, "#e63946"), + generate_donut_svg(73, "#0d6efd"), + generate_donut_svg(90, "#198754") +] + +# Attach donuts as inline images +for i, svg in enumerate(donut_svgs, start=1): + png_bytes = cairosvg.svg2png(bytestring=svg.encode("utf-8")) + img = MIMEImage(png_bytes, "png") + cid = f"donut{i}" + img.add_header("Content-ID", f"<{cid}>") + message.attach(img) + body += f'
Donut{i}' + +# Attach the final HTML body +message.attach(MIMEText(f"{body}", "html")) + +# Send the email +try: + server = smtplib.SMTP("smtp.gmail.com", 587) + server.starttls() + server.login(sender_email, password) + server.sendmail(sender_email, receiver_emails, message.as_string()) + print("✅ Email sent successfully with embedded donut PNGs!") +except Exception as e: + print("❌ Error:", e) +finally: + server.quit() diff --git a/python-email-sender/test-mail-sender-body-file.py b/python-email-sender/test-mail-sender-body-file.py new file mode 100644 index 0000000..2706a38 --- /dev/null +++ b/python-email-sender/test-mail-sender-body-file.py @@ -0,0 +1,35 @@ +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +import os + +# Sender and receiver +sender_email = "marcoioitsoft@gmail.com" +receiver_emails = ["vikasnale@gmail.com", "vikas@marcoaiot.com"] +password = "qrtq wfuj hwpp fhqr" # Use Gmail App Password here + +# Read body from text file (e.g., body.txt in the same folder) +file_path = os.path.join(os.path.dirname(__file__), "body.txt") +with open(file_path, "r", encoding="utf-8") as f: + body = f.read() + +# Create the email +message = MIMEMultipart() +message["From"] = sender_email +message["To"] =", ".join(receiver_emails) +message["Subject"] = "Test Email from Python" + +# Attach body +message.attach(MIMEText(body, "html")) + +try: + # Connect to Gmail SMTP server + server = smtplib.SMTP("smtp.gmail.com", 587) + server.starttls() # Secure the connection + server.login(sender_email, password) + server.sendmail(sender_email, receiver_emails, message.as_string()) + print("✅ Email sent successfully!") +except Exception as e: + print("❌ Error:", e) +finally: + server.quit() diff --git a/python-email-sender/test-mail-sender.py b/python-email-sender/test-mail-sender.py new file mode 100644 index 0000000..b0c168b --- /dev/null +++ b/python-email-sender/test-mail-sender.py @@ -0,0 +1,84 @@ +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from email.mime.image import MIMEImage +import os +import cairosvg + +def generate_donut_svg(percentage, color="#0d6efd", size=120, thickness=4): + """ + Generate an inline SVG donut chart. + """ + svg = f""" + + + + + + + {percentage}% + + """ + return svg + +# Sender and receiver +sender_email = "marcoioitsoft@gmail.com" +receiver_emails = ["vikasnale@gmail.com", "vikas@marcoaiot.com", "umeshvdesai@outlook.com"] +password = "qrtq wfuj hwpp fhqr" # Use Gmail App Password here + +# Read HTML body from file +file_path = os.path.join(os.path.dirname(__file__), "body.txt") +with open(file_path, "r", encoding="utf-8") as f: + body = f.read() + +# Create the email +message = MIMEMultipart("related") +message["From"] = sender_email +message["To"] = ", ".join(receiver_emails) +message["Subject"] = "Test HTML Email with Donut Charts" + +# Generate SVGs and convert to PNGs +donut_svgs = [ + generate_donut_svg(45, "#e63946"), + generate_donut_svg(73, "#0d6efd"), + generate_donut_svg(90, "#198754") +] + +# Attach donuts as inline images +for i, svg in enumerate(donut_svgs, start=1): + png_bytes = cairosvg.svg2png(bytestring=svg.encode("utf-8")) + img = MIMEImage(png_bytes, "png") + cid = f"donut{i}" + img.add_header("Content-ID", f"<{cid}>") + message.attach(img) + body += f'
Donut{i}' + +# Attach the final HTML body +message.attach(MIMEText(f"{body}", "html")) + +# Send the email +try: + server = smtplib.SMTP("smtp.gmail.com", 587) + server.starttls() + server.login(sender_email, password) + server.sendmail(sender_email, receiver_emails, message.as_string()) + print("✅ Email sent successfully with embedded donut PNGs!") +except Exception as e: + print("❌ Error:", e) +finally: + server.quit() From 023691d0629b5329c0a8fe81e45c45f28070433b Mon Sep 17 00:00:00 2001 From: Vikas Nale Date: Tue, 30 Sep 2025 20:36:55 +0530 Subject: [PATCH 2/3] Add systemd monitor for our all services like mysql, mongod and some container Refer : https://wiki.marcoaiot.com/index.php/Systemd_Monitor for more details about setup and maintenance --- python-process-monitor/.env | 11 ++ .../python-process-monitor.py | 114 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 python-process-monitor/.env create mode 100644 python-process-monitor/python-process-monitor.py diff --git a/python-process-monitor/.env b/python-process-monitor/.env new file mode 100644 index 0000000..0bb26c0 --- /dev/null +++ b/python-process-monitor/.env @@ -0,0 +1,11 @@ +# Services & Containers +SERVICES=nginx,rocketchat,mongod,mysql +CONTAINERS=redmine-app,mediawiki-app,sonarqube,postgres-sonar,ecc269bb3ba3 + +# Mail settings +SENDER_EMAIL=marcoioitsoft@gmail.com +RECEIVER_EMAIL=umesh@marcoaiot.com,vikas@marcoaiot.com +SMTP_SERVER=smtp.gmail.com +SMTP_PORT=587 +SMTP_USER=marcoioitsoft@gmail.com +SMTP_PASSWORD=qrtq wfuj hwpp fhqr \ No newline at end of file diff --git a/python-process-monitor/python-process-monitor.py b/python-process-monitor/python-process-monitor.py new file mode 100644 index 0000000..ea15b81 --- /dev/null +++ b/python-process-monitor/python-process-monitor.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 + +import subprocess +import smtplib +import os +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from dotenv import load_dotenv + +load_dotenv() + +# ----------------- CONFIG ----------------- +services = os.getenv("SERVICES", "").split(",") +containers = os.getenv("CONTAINERS", "").split(",") # update with your container names + +sender_email = os.getenv("SENDER_EMAIL", "") +receiver_email =os.getenv("RECEIVER_EMAIL", "").split(",") +smtp_server = os.getenv("SMTP_SERVER", "") +smtp_port = os.getenv("SMTP_PORT", "") +smtp_user = os.getenv("SMTP_USER", "") +smtp_password = os.getenv("SMTP_PASSWORD", "") +# ------------------------------------------ + +def run_cmd(cmd): + return subprocess.getoutput(cmd) + +def check_service(service): + status = subprocess.run(["systemctl", "is-active", service], capture_output=True, text=True) + if status.returncode == 0: + return True, "" + else: + for attempt in range(2): + print("Attempting to start: " + service) + subprocess.run(["systemctl", "restart", service]) + status = subprocess.run(["systemctl", "is-active", service], capture_output=True, text=True) + if status.returncode == 0: + return True, "" + logs = run_cmd(f"journalctl -u {service} -n 20 --no-pager") + return False, logs + +def check_container(container): + status = run_cmd(f"docker inspect -f '{{{{.State.Running}}}}' {container}") + if status.strip() == "true": + return True, "" + else: + for attempt in range(2): + run_cmd(f"docker restart {container}") + status = run_cmd(f"docker inspect -f '{{{{.State.Running}}}}' {container}") + if status.strip() == "true": + return True, "" + logs = run_cmd(f"docker logs --tail 20 {container}") + return False, logs + +def send_email(failures): + if not failures: + return + + msg = MIMEMultipart("alternative") + msg["From"] = sender_email + msg["To"] = ", ".join(receiver_email) + msg["Subject"] = "Service/Container Failure Report" + + # HTML Email Body + html = """ + + +

⚠️ Failure Report

+

The following services/containers failed even after restart attempts:

+
+ """ + + for name, logs in failures.items(): + html += f""" +
+

❌ {name} Failed

+

Last 20 log lines:

+
{logs}
+
+ """ + + html += """ +
+

This is an automated alert. Please check the server immediately.

+ + + """ + + msg.attach(MIMEText(html, "html")) + + with smtplib.SMTP(smtp_server, smtp_port) as server: + server.starttls() + server.login(smtp_user, smtp_password) + server.sendmail(sender_email, receiver_email, msg.as_string()) + +if __name__ == "__main__": + failures = {} + print("inside __main__") + for service in services: + print("looping services: " + service) + ok, logs = check_service(service) + print(ok) + print(logs) + if not ok: + failures[service] = logs + + for container in containers: + ok, logs = check_container(container) + print("looping containers: " + container) + print(ok) + print(logs) + if not ok: + failures[f"Docker: {container}"] = logs + print(failures) + send_email(failures) From e79646cc04010a31a9816e3f1d798b3415e6ce18 Mon Sep 17 00:00:00 2001 From: Vikas Nale Date: Wed, 26 Nov 2025 17:52:18 +0530 Subject: [PATCH 3/3] add s3 migration --- aws-s3-migration/aws-s3-migrate-documents.py | 246 ++ aws-s3-migration/config.json | 18 + aws-s3-migration/readme.MD | 1 + mailling/mail-templates/dpr.html | 4 +- python-email-sender/body copy 2.html | 2670 +++++++++++++++++ python-email-sender/body copy.html | 636 ++++ python-email-sender/body.html | 914 ++++++ python-email-sender/body.txt | 599 ---- python-email-sender/multipart-email.py | 89 + .../test-mail-sender-body-file.py | 4 +- 10 files changed, 4578 insertions(+), 603 deletions(-) create mode 100644 aws-s3-migration/aws-s3-migrate-documents.py create mode 100644 aws-s3-migration/config.json create mode 100644 aws-s3-migration/readme.MD create mode 100644 python-email-sender/body copy 2.html create mode 100644 python-email-sender/body copy.html create mode 100644 python-email-sender/body.html delete mode 100644 python-email-sender/body.txt create mode 100644 python-email-sender/multipart-email.py diff --git a/aws-s3-migration/aws-s3-migrate-documents.py b/aws-s3-migration/aws-s3-migrate-documents.py new file mode 100644 index 0000000..c6dbbec --- /dev/null +++ b/aws-s3-migration/aws-s3-migrate-documents.py @@ -0,0 +1,246 @@ +import json +import os +import mysql.connector +import boto3 +import sys + +# --- Configuration Loading --- + +CONFIG_FILE = 'config.json' + +def load_config(): + """Loads configuration from config.json.""" + if not os.path.exists(CONFIG_FILE): + print(f"Error: Configuration file '{CONFIG_FILE}' not found.") + sys.exit(1) + try: + with open(CONFIG_FILE, 'r') as f: + return json.load(f) + except json.JSONDecodeError as e: + print(f"Error decoding JSON in config file: {e}") + sys.exit(1) + +# --- S3 Helper Functions --- + +def generate_new_s3_key(old_key, prefix): + """ + Generates a new S3 key by prepending the destination prefix to the old key, + thereby preserving the original path structure. + """ + if not isinstance(old_key, str) or not old_key: + return None + + # Ensure the prefix ends with a slash if it's not empty and doesn't already end with one. + prefixed_path = prefix + if prefix and not prefix.endswith('/'): + prefixed_path += '/' + + # Combine the prefix and the old key. If the old key starts with a slash, strip it. + final_key = old_key.lstrip('/') + + return f"{prefixed_path}{final_key}" + + +def move_s3_object(s3_client, source_bucket, source_key, dest_bucket, dest_key): + """ + Performs the S3 'move' operation (Copy + Delete). + + Returns True on success, False otherwise. + """ + copy_source = { + 'Bucket': source_bucket, + 'Key': source_key + } + + try: + print(f" -> Copying '{source_key}' to '{dest_key}' in '{dest_bucket}'...") + # 1. Copy the object + s3_client.copy_object( + CopySource=copy_source, + Bucket=dest_bucket, + Key=dest_key + ) + print(" -> Copy object successful.") + + # print(f" -> Deleting original object from '{source_bucket}/{source_key}'...") + # # 2. Delete the original object + # s3_client.delete_object( + # Bucket=source_bucket, + # Key=source_key + # ) + # print(" -> Delete object successful.") + return True + + except Exception as e: + print(f" -> S3 Move FAILED for {source_key}: {e}") + return False + +# --- MySQL Helper Functions --- + +def fetch_documents(db_config_full): + """ + Connects to MySQL and fetches all documents (ID and S3Key). + NOTE: db_config_full includes the 'table' key, which must be filtered out for the connection. + """ + conn = None + cursor = None + + # Separate connection parameters from the table name + table_name = db_config_full['table'] + connection_config = {k: v for k, v in db_config_full.items() if k != 'table'} + + try: + # Connect using only valid connection parameters + conn = mysql.connector.connect(**connection_config) + cursor = conn.cursor() + + print(f"Fetching document IDs and S3Keys from table: {table_name}...") + + # Select all ID and S3Key (or whatever column holds the key) + query = f"SELECT ID, S3Key FROM {table_name} order by UploadedAt desc limit 10" + cursor.execute(query) + + # Fetch results as a list of dictionaries/tuples + documents = cursor.fetchall() + print(f"Found {len(documents)} documents to process.") + return documents + + except mysql.connector.Error as err: + print(f"MySQL Error: {err}") + return [] + + finally: + if cursor: + cursor.close() + if conn and conn.is_connected(): + conn.close() + +def update_document_key(db_config_full, doc_id, new_s3_key): + """ + Updates the S3Key for a specific document ID in the database. + NOTE: db_config_full includes the 'table' key, which must be filtered out for the connection. + """ + conn = None + cursor = None + + # Separate connection parameters from the table name + table_name = db_config_full['table'] + connection_config = {k: v for k, v in db_config_full.items() if k != 'table'} + + try: + # Connect using only valid connection parameters + conn = mysql.connector.connect(**connection_config) + cursor = conn.cursor() + + # Prepare the UPDATE query + update_query = ( + f"UPDATE {table_name} SET S3Key = %s WHERE ID = %s" + ) + + cursor.execute(update_query, (new_s3_key, doc_id)) + + # Commit the transaction to apply the changes + conn.commit() + print(f" -> DB Update SUCCESS for ID {doc_id}.") + return True + + except mysql.connector.Error as err: + print(f" -> DB Update FAILED for ID {doc_id}: {err}. Rolling back.") + if conn: + conn.rollback() + return False + + finally: + if cursor: + cursor.close() + if conn and conn.is_connected(): + conn.close() + +# --- Main Migration Logic --- + +def main(): + """Executes the S3 migration and database update workflow.""" + config = load_config() + + # Initialize S3 Client + aws_config = config['aws'] + try: + s3_client = boto3.client( + 's3', + aws_access_key_id=aws_config['aws_access_key_id'], + aws_secret_access_key=aws_config['aws_secret_access_key'], + region_name=aws_config['aws_region'] + ) + print("S3 client initialized successfully.") + except Exception as e: + print(f"Failed to initialize S3 client: {e}") + return + + # Fetch Documents + documents = fetch_documents(config['mysql']) + if not documents: + print("No documents found or failed to connect to the database. Exiting.") + return + + source_bucket = aws_config['source_bucket'] + dest_bucket = aws_config['destination_bucket'] + key_prefix = aws_config['destination_key_prefix'] + + success_count = 0 + failure_count = 0 + + print("\n--- Starting Document Migration Process ---") + + for doc_id, old_s3_key in documents: + print(f"\nProcessing Document ID: {doc_id}, Old Key: {old_s3_key}") + + if not old_s3_key: + print(f" -> Skipping ID {doc_id}: S3Key is empty.") + failure_count += 1 + continue + + # 1. Generate new key, preserving path structure + new_s3_key = generate_new_s3_key(old_s3_key, key_prefix) + if not new_s3_key: + print(f" -> Skipping ID {doc_id}: Could not generate new key from old key.") + failure_count += 1 + continue + + print(f" -> Calculated New Key: {new_s3_key}") + + # 2. Move S3 object (Copy + Delete) + move_successful = move_s3_object( + s3_client, + source_bucket, + old_s3_key, + dest_bucket, + new_s3_key + ) + + if move_successful: + # 3. Update database + db_update_successful = update_document_key( + config['mysql'], + doc_id, + new_s3_key + ) + + if db_update_successful: + success_count += 1 + else: + # If DB update fails, the S3 object is MOVED. Log critical error. + print(f"CRITICAL: DB update failed for ID {doc_id}. Object is MOVED to {dest_bucket}/{new_s3_key}. Manual DB correction needed.") + failure_count += 1 + else: + # If S3 move failed, the object remains in the source bucket. + print(f"S3 move failed for ID {doc_id}. Object remains in {source_bucket}/{old_s3_key}. DB not updated.") + failure_count += 1 + + + print("\n--- Migration Summary ---") + print(f"Total documents processed: {len(documents)}") + print(f"Successful migrations (S3 Move + DB Update): {success_count}") + print(f"Failed migrations: {failure_count}") + +if __name__ == "__main__": + main() diff --git a/aws-s3-migration/config.json b/aws-s3-migration/config.json new file mode 100644 index 0000000..517b819 --- /dev/null +++ b/aws-s3-migration/config.json @@ -0,0 +1,18 @@ +{ + "mysql": { + "host": "147.93.98.152", + "user": "devuser", + "password": "AppUser@123$", + "database": "MarcoBMSStage", + "table": "Documents" + }, + "aws": { + "aws_access_key_id": "AKIARZDBH3VDKXLBMDX6", + "aws_secret_access_key": "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", + "aws_region": "us-east-1", + "source_bucket": "testenv-marco-pms-documents", + "destination_bucket": "tryenv-marco-pms-documents", + "destination_key_prefix": "", + "destination_key_prefix_how": "IMPORTANT: The original S3Key (e.g., 'reports/2024/doc.pdf') will be APPENDED to this prefix, preserving the path structure. Resulting Key: 'migrated_files/reports/2024/doc.pdf'" + } +} \ No newline at end of file diff --git a/aws-s3-migration/readme.MD b/aws-s3-migration/readme.MD new file mode 100644 index 0000000..94a2fb9 --- /dev/null +++ b/aws-s3-migration/readme.MD @@ -0,0 +1 @@ +https://wiki.marcoaiot.com/index.php/AWS_S3_Migration_Script \ No newline at end of file diff --git a/mailling/mail-templates/dpr.html b/mailling/mail-templates/dpr.html index d94e57d..60c426a 100644 --- a/mailling/mail-templates/dpr.html +++ b/mailling/mail-templates/dpr.html @@ -473,8 +473,8 @@
-
- 73% +
+ 0%
diff --git a/python-email-sender/body copy 2.html b/python-email-sender/body copy 2.html new file mode 100644 index 0000000..ab915e5 --- /dev/null +++ b/python-email-sender/body copy 2.html @@ -0,0 +1,2670 @@ + + + + + + + + + + + + Email Template + + + + + + + + + + + + +
+ + + + +
+
+ + + + +
 
+
+ + + + +
 
+ + + + + + + + + + + +
+ + + + + + +
+ + + + + +
+  
+ + + + + + + +
+ + View + Online + + + + FORWARD + +
+ + + + +
+  
+ +
+
+
+ + + + + + +
+ + + + + +
+  
+ + + + + + + + + + +
+ + + + + +
+  
+ +
+
+
+ + + + +
 
+ + + + + + + + + + +
+ + + + +
  +
+ + + + + + +
  +
+ +
+ + + + +
 
+ + + + + + + + + + +
+
+ + + + + + +
+ + + + +
+  
+ +
+ Education’s purpose is to replace an empty mind with an open one. +
+ + + + +
+  
+ + +
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis + nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +
+ + + + +
+  
+ + + + + + + +
+ + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+
+ + + + + +
+  
+ +
+
+ + + + +
  +
+ +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + +
+ + + + +
+  
+ +
+ PROGRESSIVE
PROGRAMS
+
+ + + + +
+  
+ +
+ + + +
+ + + + + + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+ +
+
+ + + + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+ + + + +
+  
+ +
+ ONLINE
EDUCATION
+
+ + + + +
+  
+ +
+ + + +
+ + + + + + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+ +
+
+ + + + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+ + + + +
+  
+ +
+ ELECTRONIC
BOOK STORE
+
+ + + + +
+  
+ +
+ + + +
+ + + + + + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+ +
+
+
+ + + + +
  +
+ +
+ + + + + + + + + + +
+ + + + + +
+  
+ +
+ OUR TEAM +
+ + + + +
+  
+ + + + + +
+ + + + +
 
+
+ + + + +
+  
+ +
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. +
+ + + + +
+  
+ +
+ Еnim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex + ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit. +
+ + + + +
+  
+ + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ + + + +
+  
+ +
+ Jessica Doe +
+
+ English Teacher +
+ +
+
+
+ +
+ +
+ + + + +
+
+ + + + +
+  
+ +
+ Jessica Doe +
+
+ English Teacher +
+ +
+
+
+ +
+ +
+ + + + +
+
+ + + + +
+  
+ +
+ Jessica Doe +
+
+ English Teacher +
+ +
+
+ + + + + +
+  
+ + + + + + + +
+ + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+
+ + + + + + +
+  
+ +
+
+ + + + +
  +
+ +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + +
+ + + + +
+ + + + +
+  
+ +
+ Duis mattis luctus ligula, sit amet venenatis +
+ + + + +
+  
+ +
+ Proin vestibulum mauris ut lectus ultrices, et gravida leo + placerat. +
+ + + + +
+  
+ +
+
+ + + + + +
+
+ + + + +
+  
+ +
+ + + + + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+ + + + + +
+  
+ +
+
+
+ + + + +
+  
+ + +
+ + + + +
  +
+ +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + +
+ + + + +
+ + + + +
+  
+ +
+ Duis mattis luctus ligula, sit amet venenatis +
+ + + + +
+  
+ +
+ Proin vestibulum mauris ut lectus ultrices, et gravida leo + placerat. +
+ + + + +
+  
+ +
+
+ + + + + +
+
+ + + + +
+  
+ +
+ + + + + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+ + + + + +
+  
+ +
+
+
+ + + + +
+  
+ + +
+ + + + +
  +
+ +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + +
+ + + + +
+ + + + +
+  
+ +
+ Duis mattis luctus ligula, sit amet venenatis +
+ + + + +
+  
+ +
+ Proin vestibulum mauris ut lectus ultrices, et gravida leo + placerat. +
+ + + + +
+  
+ +
+
+ + + + + +
+
+ + + + +
+  
+ +
+ + + + + + + + + +
+ + + + +
+  
+ + + + + + +
+  
+ +
+ + + + + +
+  
+ +
+
+
+ + + + +
+  
+ + +
+ + + + +
  +
+ +
+ + + + + + + + + + +
+ + + + + +
+  
+ + + + + + +
+
+ Online Store   +
+ + + + +
+  
+ + + + + +
 
+ + + + +
+  
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
  +
+
+ + + + +
+  
+ +
+ Product Title Placeholder +
+ + + + +
+  
+ + +
+ Morbi lacinia consectetur lacus, ac fermentum quam laoreet at. + +
+ + + + +
+  
+ + +
+ Price: $19.99 $15.69 +
+ + + + +
+  
+ + + + + + + + +
+ + + + +
+  
+ +
+ + View More + +
+ + + + +
+  
+ +
+ + + + + +
+  
+ +
+
+
+ +
+ +
+ + + + +
+ + + + + +
  +
+
+ + + + +
+  
+ +
+ Product Title Placeholder +
+ + + + +
+  
+ + +
+ Morbi lacinia consectetur lacus, ac fermentum quam laoreet at. + +
+ + + + +
+  
+ + +
+ Price: $19.99 $15.69 +
+ + + + +
+  
+ + + + + + + + +
+ + + + +
+  
+ +
+ + View More + +
+ + + + +
+  
+ +
+ + + + + +
+  
+ +
+
+
+ +
+ +
+ + + + +
+ + + + + +
  +
+
+ + + + +
+  
+ +
+ Product Title Placeholder +
+ + + + +
+  
+ + +
+ Morbi lacinia consectetur lacus, ac fermentum quam laoreet at. + +
+ + + + +
+  
+ + +
+ Price: $19.99 $15.69 +
+ + + + +
+  
+ + + + + + + + +
+ + + + +
+  
+ +
+ + View More + +
+ + + + +
+  
+ +
+ + + + + +
+  
+ +
+
+ + + + + + +
+  
+ +
+
+ + + + +
  +
+ +
+ + + + + + + + + + +
+ + + + + +
+  
+ + + + + + + + + + + + + + +
+ + + + +
+
+
+
+
+ +
+ +
+ + + + +
+
+ Praesent pulvinar nulla mauris, a semper orci blandit eu +
+ + + + +
+  
+ + + + + +
+  
+ + + + + +
+  
+ + + + + + + + +
+ + + + +
+  
+ +
+
+ Sed porta elit justo, ac consectetur +
+
+ + + + +
+  
+ + + + + + + +
+ + + + +
+  
+ +
+
+ Sed vitae efficitur ante +
+
+ + + + +
+  
+ + + + + + + +
+ + + + +
+  
+ +
+
+ Praesent condimentum velit nec ipsum
dapibus varius
+
+
+ + + + +
+  
+ + + + + + + +
+  
+ + + + + + + + +
+ + + + +
+  
+ +
+ + view MORE + +
+ + + + +
+  
+ +
+ +
+
+ + + + + +
+  
+ +
+
+ + + + +
  +
+ +
+ +
+ + + + + + + + +
+ + + + +
  +
+ + + + + + + + + + +
+ + + + +
+
+ EDUCATION BOOKS +
+ + + + +
+  
+ +
+ Email template from mailbakery +
+
+ +
+
+ + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+
+ + + + +
  +
+ + + + + + + + + + +
+ + + + +
+
+ + East Pixel Bld. 99, Creative City + 9000, Republic of Design
Phone: +1 (123) 456-789 +
+
+
+ +
+
+ + + + +
+ + + + +
+ + + + + +
+
+ + Update +   |   + +
+
+
+ Unsubscribe +
+
+
+
+
+ + + + +
  +
+ +
+ + + + +
 
+ + +
+
+ + + \ No newline at end of file diff --git a/python-email-sender/body copy.html b/python-email-sender/body copy.html new file mode 100644 index 0000000..5aefa18 --- /dev/null +++ b/python-email-sender/body copy.html @@ -0,0 +1,636 @@ + + + + + + Daily Progress Report + + + + +
+ +
+

Daily Progress Report

+
+ Project: ANP ultimas wakad
+ Date: 17 September 2025 +
+
+ + +
+ * Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC +
+ + +
+ + + + + + + + + + + + + + + +
+
+

TODAY'S ATTENDANCE

+
+ + +
+ +
+ 20 / 30 +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+
+

DAILY TASKS COMPLETED

+
+ + +
+ +
+ 20 / 30 +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+
+

DAILY TASKS COMPLETED

+

20 / 30

+

Team member present

+ +
+
Completed
+
In Progress
+
Pending
+
+
+
+
+

PROJECT COMPLETION STATUS

+

20 / 30

+

Team member present

+
+
Completed
+
In Progress
+
Pending
+
+
+
+
+

Regularization Pending

+

28/32

+ +

Regularization Pending

+
+
Completed
+
In Progress
+
Pending
+
+
+
+
+ +
+

Checkout Pending

+
+ + +
+ + +
+ +
+ 73% +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+ + +
+
+

Team members present on the site

+
+
+
+
+
+
+

Activity Report Pending

+
+
+ + +
+ +
+ 73% +
+ +
+ + +
+
+ Completed +
+
+ In Progress +
+
+ Pending +
+ +
+ +
+
+
+

Team members present on the site

+
+
+
+
+
+ +
+

Team Strength on Site

+
+ + + + + + + + + + + + + + + + + + + + + +
Site Engineer1
Weilder15
Helper2
Painter1
+
+
+ + + + + + + + + + + + +
+ + +
+

Activities (Tasks) Performed 17-Sep-2025

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NAMEJOB ROLECHECK INCHECK OUT
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
+
+ + + +
+ You have received this email because it contains important information about your Marco PMS Account account. +
+
+ + + \ No newline at end of file diff --git a/python-email-sender/body.html b/python-email-sender/body.html new file mode 100644 index 0000000..dd08f1d --- /dev/null +++ b/python-email-sender/body.html @@ -0,0 +1,914 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+ + + +
+
+ +
+ + + + + + + + +
+ +
+

Daily Progress Report

+
+ +
+ + +
+
+
+ + +
+
+ +
+ + + + + + + + +
+ +
+
+ Project: ANP ultimas wakad
+ Date: 17 September 2025 +
+
+ +
+ + +
+
+
+ + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+ + + + + + + + +
+ + +

+ * Project Stats Reported as 18-Sep-25 03:30:03 UTC
* Report is based on Data + submitted on Date 17-Sep-25
+

+ + +
+ + +
+
+
+ + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+ + + + + + + + +
+ +
+
+

Regularization Pending

+

+ 28/32

+ +

Regularization + Pending

+
+
Completed +
+
In Progress +
+
Pending +
+
+
+
+ +
+ + +
+
+
+ + +
+
+ +
+ + + + + + + + +
+ +
+
+

DAILY TASKS COMPLETED +

+

+ 28/32

+ +

Team members present + on the site

+
+
Completed +
+
In Progress +
+
Pending +
+
+
+
+ +
+ + +
+
+
+ + +
+
+ +
+ + + + + + + + +
+ +
+
+

Project Completed

+

+ 28/32

+ +

PROJECT COMPLETION + STATUS

+
+
Completed +
+
In Progress +
+
Pending +
+
+
+
+ +
+ + +
+
+
+ + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+ + + + + + + + +
+ + +

+ Activities (Tasks PErformed on 17-Sep-2025 +

+ + +
+ + +
+
+
+ + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Name

+
+

Job Role

+
+ ​ + ​
+

Siddharth Badre

+
+ ​ + ​ + ​
+ ​ + ​ + ​ + ​
+ ​ + ​ + ​ + ​
+ ​ + ​ + ​ + ​
+ ​ + ​ + ​ + ​
+ +
+ + +
+
+
+ + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Add header text

+
+ ​
+

Add text

+
+ ​
+ ​ + ​
+ +
+ + +
+
+
+ + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+ + + +
+
+
+ + +
+
+
+ + + + +
+ + + + + \ No newline at end of file diff --git a/python-email-sender/body.txt b/python-email-sender/body.txt deleted file mode 100644 index 67787e4..0000000 --- a/python-email-sender/body.txt +++ /dev/null @@ -1,599 +0,0 @@ - - - - - - Daily Progress Report - - - - -
- -
-

Daily Progress Report

-
- Project: ANP ultimas wakad
- Date: 17 September 2025 -
-
- - -
- * Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC -
- - -
-
-

TODAY'S ATTENDANCE

-
- - -
- -
- 20 / 30 -
- -
- - -
-
- Completed -
-
- In Progress -
-
- Pending -
- -
- -
-
-
-

Team members present on the site

-
-
-
- -
-

DAILY TASKS COMPLETED

-
- - -
- -
- 20 / 30 -
- -
- - -
-
- Completed -
-
- In Progress -
-
- Pending -
- -
- -
-
-
-

Team members present on the site

-
-
-
-
-

DAILY TASKS COMPLETED

-

20 / 30

-

Team member present

- -
-
Completed
-
In Progress
-
Pending
-
-
- -
-

PROJECT COMPLETION STATUS

-

20 / 30

-

Team member present

-
-
Completed
-
In Progress
-
Pending
-
-
- -
-

Regularization Pending

-

28/32

-

Regularization Pending

-
-
Completed
-
In Progress
-
Pending
-
-
- -
- -
-

Checkout Pending

-
- - -
- - -
- -
- 73% -
- -
- - -
-
- Completed -
-
- In Progress -
-
- Pending -
- -
- -
- - -
-
-

Team members present on the site

-
-
-
-
-
-

Activity Report Pending

-
-
- - -
- -
- 73% -
- -
- - -
-
- Completed -
-
- In Progress -
-
- Pending -
- -
- -
-
-
-

Team members present on the site

-
-
-
-
- -
-

Team Strength on Site

-
- - - - - - - - - - - - - - - - - - - - - -
Site Engineer1
Weilder15
Helper2
Painter1
-
-
- - -
-

Activities (Tasks) Performed 17-Sep-2025

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NAMEJOB ROLECHECK INCHECK OUT
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
Siddharth BardeSite Engineer17-Sep-2025 11:47 AM-
-
- - - -
- You have received this email because it contains important information about your Marco PMS Account account. -
-
- - - \ No newline at end of file diff --git a/python-email-sender/multipart-email.py b/python-email-sender/multipart-email.py new file mode 100644 index 0000000..4fddaf2 --- /dev/null +++ b/python-email-sender/multipart-email.py @@ -0,0 +1,89 @@ +import smtplib +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.mime.image import MIMEImage +from email.mime.base import MIMEBase +from email import encoders + +# --- Email Configuration --- +# Replace with your actual email and app password +sender_password = "qrtq wfuj hwpp fhqr" +recipient_email =["vikasnale@gmail.com", "vikas@marcoaiot.com", "umeshvdesai@outlook.com"] +sender_email = "marcoioitsoft@gmail.com" +receiver_emails = ["vikasnale@gmail.com", "vikas@marcoaiot.com"] +password = "qrtq wfuj hwpp fhqr" # Use Gmail App Password here + +# --- 1. Create the top-level container (multipart/related) --- +# This container will hold the HTML body and the embedded images. +msg_root = MIMEMultipart('related') +msg_root['Subject'] = 'Python Email with Embedded Images and Attachment' +msg_root['From'] = sender_email +msg_root['To'] = recipient_email +msg_root.preamble = 'This is a multi-part message in MIME format.' + +# --- 2. Create the alternative container (multipart/alternative) --- +# This part holds both the plain-text and HTML versions of the email content. +msg_alternative = MIMEMultipart('alternative') +msg_root.attach(msg_alternative) + +# --- Define the plain text and HTML content --- +plain_text_content = """\ +Hello, +This is the plain text version of the email. +The images are not visible here. +Please view this email in a client that supports HTML to see the embedded images. +""" + +html_content = """\ + + +

Hello,

+

This email contains two embedded images and one regular attachment.

+

Here is the first image (CID):

+ First Image +

And here is the second one (CID):

+ Company Logo +

Please see the attached PDF for more information.

+ + +""" + +# Attach the plain text and HTML versions to the alternative container +msg_alternative.attach(MIMEText(plain_text_content, 'plain')) +msg_alternative.attach(MIMEText(html_content, 'html')) + +# --- 3. Attach the embedded images with Content-ID (CID) --- +# The Content-ID is crucial for the HTML body to reference the image. +# The 'inline' disposition makes sure the image is displayed within the email body. + +# Attach 'image1.jpg' +with open('image1.jpg', 'rb') as fp: + msg_image1 = MIMEImage(fp.read(), _subtype="jpeg") + msg_image1.add_header('Content-ID', '') + msg_image1.add_header('Content-Disposition', 'inline') + msg_root.attach(msg_image1) + +# Attach 'logo.png' +with open('logo.png', 'rb') as fp: + msg_logo = MIMEImage(fp.read(), _subtype="png") + msg_logo.add_header('Content-ID', '') + msg_logo.add_header('Content-Disposition', 'inline') + msg_root.attach(msg_logo) + +# --- 4. Attach the regular attachment --- +# This part is for the file that should be a standard attachment. +with open('document.pdf', 'rb') as fp: + part = MIMEBase('application', 'pdf') + part.set_payload(fp.read()) + encoders.encode_base64(part) + part.add_header('Content-Disposition', 'attachment', filename='document.pdf') + msg_root.attach(part) + +# --- 5. Send the email using SMTP --- +try: + with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp: + smtp.login(sender_email, sender_password) + smtp.send_message(msg_root) + print("Email sent successfully!") +except Exception as e: + print(f"Failed to send email: {e}") \ No newline at end of file diff --git a/python-email-sender/test-mail-sender-body-file.py b/python-email-sender/test-mail-sender-body-file.py index 2706a38..03f7ecc 100644 --- a/python-email-sender/test-mail-sender-body-file.py +++ b/python-email-sender/test-mail-sender-body-file.py @@ -5,11 +5,11 @@ import os # Sender and receiver sender_email = "marcoioitsoft@gmail.com" -receiver_emails = ["vikasnale@gmail.com", "vikas@marcoaiot.com"] +receiver_emails = ["garu.vikas@gmail.com", "vikas@marcoaiot.com" ,"umeshvdesai@outlook.com"] password = "qrtq wfuj hwpp fhqr" # Use Gmail App Password here # Read body from text file (e.g., body.txt in the same folder) -file_path = os.path.join(os.path.dirname(__file__), "body.txt") +file_path = os.path.join(os.path.dirname(__file__), "body.html") with open(file_path, "r", encoding="utf-8") as f: body = f.read()