version 1

This commit is contained in:
Vikas Nale 2025-09-19 18:11:31 +05:30
parent 2696003a09
commit 3c379a9bf2
8 changed files with 1724 additions and 0 deletions

View File

@ -0,0 +1,157 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Donut Variants</title>
<style>
.donut {
--percentage: 65; /* Change this per chart */
--primary: #e63946; /* Fill color */
--track: #e9ecef; /* Background track */
--size: 120px; /* Default size */
--thickness: 20px; /* Default thickness */
width: var(--size);
height: var(--size);
border-radius: 50%;
background: conic-gradient(
var(--primary) calc(var(--percentage) * 1%),
var(--track) 0
);
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-family: Arial, sans-serif;
font-weight: bold;
color: #333;
}
.donut::before {
content: "";
position: absolute;
width: calc(var(--size) - var(--thickness));
height: calc(var(--size) - var(--thickness));
border-radius: 50%;
background: #fff; /* Inner cut-out */
}
.donut span {
position: absolute;
font-size: calc(var(--size) / 6);
}
/* Variants */
.donut.thin {
--size: 80px;
--thickness: 12px;
}
.donut.medium {
--size: 120px;
--thickness: 25px;
}
.donut.large {
--size: 180px;
--thickness: 35px;
}
.progress {
width: 100%;
background-color: #e9ecef;
border-radius: 0.375rem;
overflow: hidden;
height: 0.51rem; /* Default height */
margin-bottom: 1rem;
font-family: Arial, sans-serif;
font-size: 0.375rem; /* Default size */
font-weight: 500;
}
.progress.thin {
height: 0.7rem;
font-size: 0.6rem;
}
.progress.medium {
height: 1rem;
font-size: 0.7rem;
}
.progress.large {
height: 1.5rem;
font-size: 1.2rem;
}
.progress-bar {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
background-color: #0d6efd; /* default = Bootstrap primary */
transition: width 0.6s ease;
}
/* Color variants */
.progress-bar-success {
background-color: #198754;
}
.progress-bar-warning {
background-color: #ffc107;
color: #000;
}
.progress-bar-danger {
background-color: #dc3545;
}
</style>
</head>
<body style="display:block; gap:40px; align-items:center; justify-content:center; min-height:100vh;">
<div style="
display: flex;
vertical-align: middle;
">
<!-- Thin -->
<div class="donut thin" style="--percentage: 45;">
<span>45%</span>
</div>
<!-- Medium -->
<div class="donut medium" style="--percentage: 73;">
<span>73%</span>
</div>
<!-- Large -->
<div class="donut large" style="--percentage: 90;">
<span>90%</span>
</div>
</div>
<div style="
margin-top: 100px;
">
<div class="progress" style="width:200px">
<div class="progress-bar" style="width: 25%;">25%</div>
</div>
<div class="progress thin " style="width:200px">
<div class="progress-bar progress-bar-success" style="width: 50%;">50%</div>
</div>
<div class="progress medium" style="width:200px">
<div class="progress-bar progress-bar-warning" style="width: 75%;">75%</div>
</div>
<div class="progress large" style="width:50%">
<div class="progress-bar progress-bar-danger" style="width: 90%;">90%</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,598 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Daily Progress Report</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background: #f5f5f5;
color: #333;
}
.container {
max-width: 1100px;
margin: 20px auto;
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.header {
background: #b10000;
color: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.header h1 {
font-size: 22px;
margin: 0;
}
.header .project-info {
font-size: 14px;
text-align: right;
}
.status-note {
font-size: 12px;
color: #555;
padding: 15px 20px 0 20px;
}
.status-cards {
display: flex;
justify-content: space-between;
gap: 15px;
padding: 20px;
flex-wrap: wrap;
}
.card {
flex: 1;
min-width: 200px;
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
text-align: center;
background: #fff;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
/* <-- added shadow */
transition: transform 0.2s ease, box-shadow 0.2s ease;
border-top: 1px solid #e63946;
}
.card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.card h3 {
font-size: 14px;
margin: 0 0 10px 0;
}
.card p {
margin: 5px 0;
}
.card .value {
font-size: 22px;
font-weight: bold;
}
.card-title {
font-size: 0.9rem;
text-transform: uppercase;
font-weight: 600;
color: #6c757d;
}
.attendance {
color: #b10000;
}
.tasks {
color: #007bff;
}
.completion {
color: #28a745;
}
.activities {
padding: 20px;
}
.activities h2 {
font-size: 18px;
margin-bottom: 10px;
}
.table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.table th,
.table td {
border: 1px solid #ddd;
padding: 8px;
text-align: center;
}
.table th {
background: #f0f0f0;
}
.footer {
background: #b10000;
color: #fff;
text-align: center;
padding: 15px;
font-size: 12px;
}
.footer a {
color: #fff;
margin: 0 8px;
text-decoration: none;
}
/* Responsive */
@media (max-width: 600px) {
.header {
flex-direction: column;
text-align: center;
}
.header .project-info {
text-align: center;
margin-top: 10px;
}
.status-cards {
flex-direction: column;
}
}
.legend {
margin-top: 10px;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
font-size: 12px;
color: #555;
}
.legend-item {
display: flex;
align-items: center;
gap: 4px;
}
.legend-color {
width: 10px;
height: 10px;
border-radius: 2px;
display: inline-block;
}
.legend-red {
background: #b10000;
}
.legend-blue {
background: #007bff;
}
.legend-green {
background: #28a745;
}
.legend-gray {
background: #ccc;
}
.donut {
--percentage: 65;
/* Change this per chart */
--danger: #e63946;
--primary: #007bff;
--warning: #ffc107;
--success: #198754;
/* Fill color */
--track: #e9ecef;
/* Background track */
--size: 120px;
/* Default size */
--thickness: 20px;
/* Default thickness */
width: var(--size);
height: var(--size);
border-radius: 50%;
background: conic-gradient(var(--danger) calc(var(--percentage) * 1%),
var(--track) 0);
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-family: Arial, sans-serif;
font-weight: bold;
color: #333;
}
.donut::before {
content: "";
position: absolute;
width: calc(var(--size) - var(--thickness));
height: calc(var(--size) - var(--thickness));
border-radius: 50%;
background: #fff;
/* Inner cut-out */
}
.donut span {
position: absolute;
font-size: calc(var(--size) / 6);
}
/* Variants */
.donut.thin {
--size: 80px;
--thickness: 12px;
}
.donut.medium {
--size: 120px;
--thickness: 25px;
}
.donut.large {
--size: 180px;
--thickness: 35px;
}
/* Color variants */
.donut-success {
background: conic-gradient(var(--success) calc(var(--percentage) * 1%),
var(--track) 0);
color: var(--success)
}
.donut-warning {
background: conic-gradient(var(--warning) calc(var(--percentage) * 1%),
var(--track) 0);
color: var(--warning)
}
.donut-danger {
background: conic-gradient(var(--danger) calc(var(--percentage) * 1%),
var(--track) 0);
color: var(--danger)
}
.donut-primary {
background: conic-gradient(var(--primary) calc(var(--percentage) * 1%),
var(--track) 0);
color: var(--primary)
}
</style>
</head>
<body>
<div class="container">
<!-- Header -->
<div class="header">
<h1>Daily Progress Report</h1>
<div class="project-info">
<strong>Project:</strong> ANP ultimas wakad<br>
<strong>Date:</strong> 17 September 2025
</div>
</div>
<!-- Status Note -->
<div class="status-note">
* Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC
</div>
<!-- Status Cards -->
<div class="status-cards">
<div class="card">
<h4 class="card-title">TODAY'S ATTENDANCE</h4>
<div style="display:flex; flex-wrap:wrap;">
<!-- Left Column -->
<div style="width:50%; box-sizing:border-box;display:flex; justify-content:center; align-items:center;">
<!-- Medium -->
<div class="donut thin" style="--percentage: 66;">
<span>20 / 30</span>
</div>
</div>
<!-- Right Column -->
<div class="legend" style="width:50%; padding:15px; box-sizing:border-box;">
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;">
<span class="legend-color legend-green"></span> Completed
</div>
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;; ">
<span class="legend-color legend-blue"></span> In Progress
</div>
<div class="legend-item"
style="margin-bottom:10px; text-align: left; display:left; justify-content:left; align-items:left!important;;">
<span class="legend-color legend-gray"></span> Pending
</div>
</div>
</div>
<div>
<div style="padding:10px; text-align:center;">
<p class="text-muted">Team members present on the site</p>
</div>
</div>
</div>
<div class="card">
<h4 class="card-title">DAILY TASKS COMPLETED</h4>
<div style="display:flex; flex-wrap:wrap;">
<!-- Left Column -->
<div style="width:50%; box-sizing:border-box;display:flex; justify-content:center; align-items:center;">
<!-- Medium -->
<div class="donut thin donut-primary" style="--percentage: 66;">
<span>20 / 30</span>
</div>
</div>
<!-- Right Column -->
<div class="legend" style="width:50%; padding:15px; box-sizing:border-box;">
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;">
<span class="legend-color legend-green"></span> Completed
</div>
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;; ">
<span class="legend-color legend-blue"></span> In Progress
</div>
<div class="legend-item"
style="margin-bottom:10px; text-align: left; display:left; justify-content:left; align-items:left!important;;">
<span class="legend-color legend-gray"></span> Pending
</div>
</div>
</div>
<div>
<div style="padding:10px; text-align:center;">
<p class="text-muted">Team members present on the site</p>
</div>
</div>
</div>
<div class="card">
<h4 class="card-title">DAILY TASKS COMPLETED</h4>
<p class="value tasks">20 / 30</p>
<p>Team member present</p>
<div class="legend">
<div class="legend-item"><span class="legend-color legend-blue"></span> Completed</div>
<div class="legend-item"><span class="legend-color legend-green"></span> In Progress</div>
<div class="legend-item"><span class="legend-color legend-gray"></span> Pending</div>
</div>
</div>
<div class="card">
<h4 class="card-title">PROJECT COMPLETION STATUS</h4>
<p class=" value completion">20 / 30</p>
<p>Team member present</p>
<div class="legend">
<div class="legend-item"><span class="legend-color legend-green"></span> Completed</div>
<div class="legend-item"><span class="legend-color legend-blue"></span> In Progress</div>
<div class="legend-item"><span class="legend-color legend-gray"></span> Pending</div>
</div>
</div>
<div class="card">
<h4 class="card-title">Regularization Pending</h4>
<p class="value tasks">28/32</p>
<p class="text-muted">Regularization Pending</p>
<div class="legend">
<div class="legend-item"><span class="legend-color legend-green"></span> Completed</div>
<div class="legend-item"><span class="legend-color legend-blue"></span> In Progress</div>
<div class="legend-item"><span class="legend-color legend-gray"></span> Pending</div>
</div>
</div>
<div class="card">
<!-- Row 1: Header -->
<div>
<h4 class="card-title">Checkout Pending</h4>
</div>
<!-- Row 2: Two Columns -->
<div style="display:flex; flex-wrap:wrap;">
<!-- Left Column -->
<div style="width:50%; box-sizing:border-box;display:flex; justify-content:center; align-items:center;">
<!-- Medium -->
<div class="donut thin donut-success" style="--percentage: 73;">
<span>73%</span>
</div>
</div>
<!-- Right Column -->
<div class="legend" style="width:50%; padding:15px; box-sizing:border-box;">
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;">
<span class="legend-color legend-green"></span> Completed
</div>
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;; ">
<span class="legend-color legend-blue"></span> In Progress
</div>
<div class="legend-item"
style="margin-bottom:10px; text-align: left; display:left; justify-content:left; align-items:left!important;;">
<span class="legend-color legend-gray"></span> Pending
</div>
</div>
</div>
<!-- Row 3: Full Width -->
<div>
<div style="padding:10px; text-align:center;">
<p class="text-muted">Team members present on the site</p>
</div>
</div>
</div>
<div class="card">
<div>
<h4 class="card-title">Activity Report Pending</h4>
</div>
<div style="display:flex; flex-wrap:wrap;">
<!-- Left Column -->
<div style="width:50%; box-sizing:border-box;display:flex; justify-content:center; align-items:center;">
<!-- Medium -->
<div class="donut thin donut-warning" style="--percentage: 73;">
<span>73%</span>
</div>
</div>
<!-- Right Column -->
<div class="legend" style="width:50%; padding:15px; box-sizing:border-box;">
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;">
<span class="legend-color legend-green"></span> Completed
</div>
<div class="legend-item"
style="margin-bottom:10px;text-align: left; display:left; justify-content:left; align-items:left!important;; ">
<span class="legend-color legend-blue"></span> In Progress
</div>
<div class="legend-item"
style="margin-bottom:10px; text-align: left; display:left; justify-content:left; align-items:left!important;;">
<span class="legend-color legend-gray"></span> Pending
</div>
</div>
</div>
<div>
<div style="padding:10px; text-align:center;">
<p class="text-muted">Team members present on the site</p>
</div>
</div>
</div>
<div class="card">
<!-- Row 1: Header -->
<div>
<h4 class="card-title">Team Strength on Site</h4>
</div>
<table style="width: 100%;">
<tr>
<td style="text-align: left;">Site Engineer</td>
<td style="text-align: right;">1</td>
</tr>
<tr>
<td style="text-align: left;">Weilder</td>
<td style="text-align: right;">15</td>
</tr>
<tr>
<td style="text-align: left;">Helper</td>
<td style="text-align: right;">2</td>
</tr>
<tr>
<td style="text-align: left;">Painter</td>
<td style="text-align: right;">1</td>
</tr>
</table>
</div>
</div>
<!-- Activities -->
<div class="activities">
<h2>Activities (Tasks) Performed 17-Sep-2025</h2>
<table class="table">
<thead>
<tr>
<th>NAME</th>
<th>JOB ROLE</th>
<th>CHECK IN</th>
<th>CHECK OUT</th>
</tr>
</thead>
<tbody>
<tr>
<td>Siddharth Barde</td>
<td>Site Engineer</td>
<td>17-Sep-2025 11:47 AM</td>
<td>-</td>
</tr>
<tr>
<td>Siddharth Barde</td>
<td>Site Engineer</td>
<td>17-Sep-2025 11:47 AM</td>
<td>-</td>
</tr>
<tr>
<td>Siddharth Barde</td>
<td>Site Engineer</td>
<td>17-Sep-2025 11:47 AM</td>
<td>-</td>
</tr>
</tbody>
</table>
</div>
<!-- Footer -->
<div class="footer" style="display:flex; flex-wrap:wrap;">
<div style="width: 50%;text-align: left;">
Contact Us: contact[at]marcoaiot.com<br>
Marco AIoT technologies Pvt. Ltd. ©2025 All Rights Reserved
</div>
<div style="width: 50%; text-align: right;">
<!-- <a href="#">Instagram</a> | -->
<a href="#"><img src="https://cdn.marcoaiot.com/icons/brands/google.png" style="height: 15px;" /></a> |
<a href="#"><img src="https://cdn.marcoaiot.com/icons/brands/twitter.png" style="height: 15px;" /></a> |
<a href="#"><img src="https://cdn.marcoaiot.com/icons/brands/facebook.png" style="height: 15px;" /></a> |
<a href="#"><img src="https://cdn.marcoaiot.com/icons/brands/instagram.png" style="height: 15px;" /></a>
<!-- <a href="#"><img src="https://cdn.marcoaiot.com/icons/brands/youtube.png" style="height: 15px;" /></a> | <a
href="#">LinkedIn</a> |
<a href="#">YouTube</a> -->
</div>
</div>
<div style="text-align: center;width: 100%;background-color: #fff;margin:10px;font-size: small;color: #6c757d ;">
You have received this email because it contains important information about your Marco PMS Account account.
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,157 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Donut Variants</title>
<style>
.donut {
--percentage: 65; /* Change this per chart */
--primary: #e63946; /* Fill color */
--track: #e9ecef; /* Background track */
--size: 120px; /* Default size */
--thickness: 20px; /* Default thickness */
width: var(--size);
height: var(--size);
border-radius: 50%;
background: conic-gradient(
var(--primary) calc(var(--percentage) * 1%),
var(--track) 0
);
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-family: Arial, sans-serif;
font-weight: bold;
color: #333;
}
.donut::before {
content: "";
position: absolute;
width: calc(var(--size) - var(--thickness));
height: calc(var(--size) - var(--thickness));
border-radius: 50%;
background: #fff; /* Inner cut-out */
}
.donut span {
position: absolute;
font-size: calc(var(--size) / 6);
}
/* Variants */
.donut.thin {
--size: 80px;
--thickness: 12px;
}
.donut.medium {
--size: 120px;
--thickness: 25px;
}
.donut.large {
--size: 180px;
--thickness: 35px;
}
.progress {
width: 100%;
background-color: #e9ecef;
border-radius: 0.375rem;
overflow: hidden;
height: 0.51rem; /* Default height */
margin-bottom: 1rem;
font-family: Arial, sans-serif;
font-size: 0.375rem; /* Default size */
font-weight: 500;
}
.progress.thin {
height: 0.7rem;
font-size: 0.6rem;
}
.progress.medium {
height: 1rem;
font-size: 0.7rem;
}
.progress.large {
height: 1.5rem;
font-size: 1.2rem;
}
.progress-bar {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
background-color: #0d6efd; /* default = Bootstrap primary */
transition: width 0.6s ease;
}
/* Color variants */
.progress-bar-success {
background-color: #198754;
}
.progress-bar-warning {
background-color: #ffc107;
color: #000;
}
.progress-bar-danger {
background-color: #dc3545;
}
</style>
</head>
<body style="display:block; gap:40px; align-items:center; justify-content:center; min-height:100vh;">
<div style="
display: flex;
vertical-align: middle;
">
<!-- Thin -->
<div class="donut thin" style="--percentage: 45;">
<span>45%</span>
</div>
<!-- Medium -->
<div class="donut medium" style="--percentage: 73;">
<span>73%</span>
</div>
<!-- Large -->
<div class="donut large" style="--percentage: 90;">
<span>90%</span>
</div>
</div>
<div style="
margin-top: 100px;
">
<div class="progress" style="width:200px">
<div class="progress-bar" style="width: 25%;">25%</div>
</div>
<div class="progress thin " style="width:200px">
<div class="progress-bar progress-bar-success" style="width: 50%;">50%</div>
</div>
<div class="progress medium" style="width:200px">
<div class="progress-bar progress-bar-warning" style="width: 75%;">75%</div>
</div>
<div class="progress large" style="width:50%">
<div class="progress-bar progress-bar-danger" style="width: 90%;">90%</div>
</div>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -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"
}
}

View File

@ -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"""
<svg width="{size}" height="{size}" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
<!-- Track -->
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e9ecef"
stroke-width="{thickness}"
/>
<!-- Progress -->
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="{color}"
stroke-width="{thickness}"
stroke-dasharray="{percentage}, 100"
/>
<!-- Label -->
<text x="18" y="20.35" fill="#333" font-size="5" text-anchor="middle">{percentage}%</text>
</svg>
"""
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'<br><img src="cid:{cid}" alt="Donut{i}">'
# Attach the final HTML body
message.attach(MIMEText(f"<html><body>{body}</body></html>", "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()

View File

@ -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()

View File

@ -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"""
<svg width="{size}" height="{size}" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
<!-- Track -->
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e9ecef"
stroke-width="{thickness}"
/>
<!-- Progress -->
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="{color}"
stroke-width="{thickness}"
stroke-dasharray="{percentage}, 100"
/>
<!-- Label -->
<text x="18" y="20.35" fill="#333" font-size="5" text-anchor="middle">{percentage}%</text>
</svg>
"""
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'<br><img src="cid:{cid}" alt="Donut{i}">'
# Attach the final HTML body
message.attach(MIMEText(f"<html><body>{body}</body></html>", "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()