পাইথনের 'email' প্যাকেজের ক্ষমতা উন্মোচন করুন। জটিল MIME মেসেজ তৈরি করতে এবং কার্যকরভাবে বিশ্বব্যাপী ডেটা নিষ্কাশনের জন্য আগত ইমেল পার্স করতে শিখুন।
পাইথনের ইমেইল প্যাকেজে দক্ষতা অর্জন: MIME মেসেজ নির্মাণ এবং শক্তিশালী পার্সিং-এর শিল্পকলা
ইমেল বিশ্বব্যাপী যোগাযোগের একটি ভিত্তিপ্রস্তর হিসেবে রয়ে গেছে, যা ব্যক্তিগত চিঠিপত্র, ব্যবসায়িক কার্যক্রম এবং স্বয়ংক্রিয় সিস্টেম বিজ্ঞপ্তির জন্য অপরিহার্য। প্রতিটি রিচ-টেক্সট ইমেল, প্রতিটি সংযুক্তি এবং প্রতিটি যত্নসহকারে ফরম্যাট করা স্বাক্ষরের পিছনে মাল্টিপারপাস ইন্টারনেট মেল এক্সটেনশন (MIME)-এর জটিলতা লুকিয়ে আছে। ডেভেলপারদের জন্য, বিশেষ করে যারা পাইথন নিয়ে কাজ করেন, তাদের জন্য প্রোগ্রামগতভাবে এই MIME বার্তাগুলি তৈরি এবং পার্স করার দক্ষতা অর্জন একটি গুরুত্বপূর্ণ স্কিল।
পাইথনের বিল্ট-ইন email
প্যাকেজ ইমেল বার্তা পরিচালনার জন্য একটি শক্তিশালী এবং ব্যাপক ফ্রেমওয়ার্ক প্রদান করে। এটি শুধু সাধারণ টেক্সট পাঠানোর জন্য নয়; এটি MIME-এর জটিল বিবরণগুলো থেকে আপনাকে দূরে রাখার জন্য ডিজাইন করা হয়েছে, যা আপনাকে অত্যাধুনিক ইমেল তৈরি করতে এবং আগত ইমেল থেকে নির্দিষ্ট ডেটা অসাধারণ নির্ভুলতার সাথে বের করতে সাহায্য করে। এই গাইডটি আপনাকে এই প্যাকেজের দুটি প্রধান দিকের গভীরে নিয়ে যাবে: পাঠানোর জন্য MIME বার্তা তৈরি করা এবং ডেটা নিষ্কাশনের জন্য সেগুলি পার্স করা, যা সর্বোত্তম অনুশীলনের উপর একটি বিশ্বব্যাপী দৃষ্টিভঙ্গি প্রদান করবে।
নির্মাণ এবং পার্সিং উভয়ই বোঝা অত্যন্ত গুরুত্বপূর্ণ। যখন আপনি একটি বার্তা তৈরি করেন, আপনি মূলত অন্য একটি সিস্টেমের ব্যাখ্যার জন্য তার কাঠামো এবং বিষয়বস্তু নির্ধারণ করছেন। যখন আপনি পার্স করেন, আপনি অন্য একটি সিস্টেম দ্বারা সংজ্ঞায়িত একটি কাঠামো এবং বিষয়বস্তু ব্যাখ্যা করছেন। একটির গভীর উপলব্ধি অন্যটিতে দক্ষতা অর্জনে ব্যাপকভাবে সহায়তা করে, যা আরও স্থিতিশীল এবং আন্তঃক্রিয়াশীল ইমেল অ্যাপ্লিকেশন তৈরি করতে সাহায্য করে।
MIME বোঝা: আধুনিক ইমেলের মূল ভিত্তি
পাইথনের নির্দিষ্ট বিবরণে যাওয়ার আগে, MIME কী এবং কেন এটি এত গুরুত্বপূর্ণ তা বোঝা অপরিহার্য। মূলত, ইমেল বার্তাগুলি প্লেইন টেক্সট (৭-বিট ASCII অক্ষর)-এ সীমাবদ্ধ ছিল। ১৯৯০-এর দশকের গোড়ার দিকে প্রবর্তিত MIME, ইমেলের ক্ষমতা বাড়িয়ে নিম্নলিখিত বিষয়গুলো সমর্থন করে:
- অ-ASCII অক্ষর: আরবি, চীনা, রাশিয়ান বা অন্য কোনো ভাষায় টেক্সট পাঠানোর সুবিধা, যা ASCII সেটের বাইরের অক্ষর ব্যবহার করে।
- সংযুক্তি: ডকুমেন্ট, ছবি, অডিও এবং ভিডিওর মতো ফাইল পাঠানো।
- রিচ টেক্সট ফরম্যাটিং: বোল্ড, ইটালিক, রঙ এবং লেআউট সহ HTML ইমেল।
- একাধিক অংশ: একটি ইমেলের মধ্যে প্লেইন টেক্সট, HTML এবং সংযুক্তি একত্রিত করা।
MIME একটি ইমেল বার্তায় নির্দিষ্ট হেডার যোগ করে এবং এর বডিকে বিভিন্ন "পার্ট" বা অংশে গঠন করে এটি সম্পন্ন করে। কিছু মূল MIME হেডার যা আপনার চোখে পড়বে:
Content-Type:
একটি অংশের ডেটার ধরণ নির্দিষ্ট করে (যেমন,text/plain
,text/html
,image/jpeg
,application/pdf
,multipart/alternative
)। এটি প্রায়শই একটিcharset
প্যারামিটারও অন্তর্ভুক্ত করে (যেমন,charset=utf-8
)।Content-Transfer-Encoding:
নির্দেশ করে যে ইমেল ক্লায়েন্ট কীভাবে বিষয়বস্তু ডিকোড করবে (যেমন, বাইনারি ডেটার জন্যbase64
, কিছু অ-ASCII অক্ষর সহ বেশিরভাগ টেক্সটের জন্যquoted-printable
)।Content-Disposition:
পরামর্শ দেয় যে প্রাপকের ইমেল ক্লায়েন্ট কীভাবে অংশটি প্রদর্শন করবে (যেমন, বার্তার বডির মধ্যে প্রদর্শনের জন্যinline
, সংরক্ষণ করার জন্য একটি ফাইলের জন্যattachment
)।
পাইথন email
প্যাকেজ: একটি গভীর পর্যালোচনা
পাইথনের email
প্যাকেজটি প্রোগ্রামগতভাবে ইমেল বার্তা তৈরি, পার্স এবং পরিবর্তন করার জন্য ডিজাইন করা একটি ব্যাপক লাইব্রেরি। এটি Message
অবজেক্টের ধারণার উপর ভিত্তি করে তৈরি, যা একটি ইমেলের কাঠামোকে উপস্থাপন করে।
প্যাকেজের মধ্যে মূল মডিউলগুলি হলো:
email.message:
মূলEmailMessage
ক্লাসটি ধারণ করে, যা ইমেল বার্তা তৈরি এবং পরিচালনা করার জন্য প্রাথমিক ইন্টারফেস। এটি একটি অত্যন্ত নমনীয় ক্লাস যা MIME বিবরণ স্বয়ংক্রিয়ভাবে পরিচালনা করে।email.mime:
লিগ্যাসি ক্লাস (যেমনMIMEText
,MIMEMultipart
) সরবরাহ করে যা MIME কাঠামোর উপর আরও স্পষ্ট নিয়ন্ত্রণ দেয়। যদিওEmailMessage
এর সরলতার কারণে নতুন কোডের জন্য সাধারণত পছন্দ করা হয়, এই ক্লাসগুলি বোঝা উপকারী হতে পারে।email.parser:
কাঁচা ইমেল ডেটা (বাইট বা স্ট্রিং) কেEmailMessage
অবজেক্টে রূপান্তর করতেBytesParser
এবংParser
এর মতো ক্লাস সরবরাহ করে।email.policy:
এমন পলিসি নির্ধারণ করে যা নিয়ন্ত্রণ করে কীভাবে ইমেল বার্তাগুলি তৈরি এবং পার্স করা হয়, যা হেডার এনকোডিং, লাইন এন্ডিং এবং ত্রুটি পরিচালনায় প্রভাব ফেলে।
বেশিরভাগ আধুনিক ব্যবহারের ক্ষেত্রে, আপনি মূলত নির্মাণ এবং পার্স করা মেসেজ অবজেক্ট উভয়ের জন্য email.message.EmailMessage
ক্লাসের সাথে কাজ করবেন। এর পদ্ধতিগুলি লিগ্যাসি email.mime
ক্লাসের সাথে যা একটি দীর্ঘ প্রক্রিয়া ছিল, তা অনেক সহজ করে তোলে।
MIME মেসেজ নির্মাণ: নির্ভুলতার সাথে ইমেল তৈরি
ইমেল নির্মাণে বিভিন্ন উপাদান (টেক্সট, HTML, সংযুক্তি) একত্রিত করে একটি বৈধ MIME কাঠামো তৈরি করা জড়িত। EmailMessage
ক্লাস এই প্রক্রিয়াটিকে উল্লেখযোগ্যভাবে সহজ করে তোলে।
সাধারণ টেক্সট ইমেল
সবচেয়ে সহজ ইমেল হলো প্লেইন টেক্সট। আপনি একটি তৈরি করতে এবং সহজেই বেসিক হেডার সেট করতে পারেন:
from email.message import EmailMessage
msg = EmailMessage()
msg['Subject'] = 'Greetings from Python'
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
msg.set_content('Hello, this is a plain text email sent from Python.\n\nBest regards,\nYour Python Script')
print(msg.as_string())
ব্যাখ্যা:
EmailMessage()
একটি খালি মেসেজ অবজেক্ট তৈরি করে।- ডিকশনারির মতো অ্যাক্সেস (
msg['Subject'] = ...
) সাধারণ হেডার সেট করে। set_content()
ইমেলের প্রাথমিক বিষয়বস্তু যোগ করে। ডিফল্টরূপে, এটিContent-Type: text/plain; charset="utf-8"
অনুমান করে।as_string()
বার্তাটিকে একটি স্ট্রিং ফরম্যাটে সিরিয়ালাইজ করে যা SMTP এর মাধ্যমে পাঠানোর বা একটি ফাইলে সংরক্ষণ করার জন্য উপযুক্ত।
HTML কন্টেন্ট যোগ করা
একটি HTML ইমেল পাঠাতে, আপনি কেবল set_content()
কল করার সময় কন্টেন্টের ধরণ উল্লেখ করবেন। যাদের ইমেল ক্লায়েন্ট HTML রেন্ডার করে না, বা অ্যাক্সেসিবিলিটির কারণে তাদের জন্য একটি প্লেইন টেক্সট বিকল্প প্রদান করা একটি ভাল অভ্যাস।
from email.message import EmailMessage
msg = EmailMessage()
msg['Subject'] = 'Your HTML Newsletter'
msg['From'] = 'newsletter@example.com'
msg['To'] = 'subscriber@example.com'
html_content = """
<html>
<head></head>
<body>
<h1>Welcome to Our Global Update!</h1>
<p>Dear Subscriber,</p>
<p>This is your <strong>latest update</strong> from around the world.</p>
<p>Visit our <a href="http://www.example.com">website</a> for more.</p>
<p>Best regards,<br>The Team</p>
</body>
</html>
"""
# Add the HTML version
msg.add_alternative(html_content, subtype='html')
# Add a plain text fallback
plain_text_content = (
"Welcome to Our Global Update!\n\n"
"Dear Subscriber,\n\n"
"This is your latest update from around the world.\n"
"Visit our website for more: http://www.example.com\n\n"
"Best regards,\nThe Team"
)
msg.add_alternative(plain_text_content, subtype='plain')
print(msg.as_string())
ব্যাখ্যা:
add_alternative()
*একই* কন্টেন্টের বিভিন্ন উপস্থাপনা যোগ করতে ব্যবহৃত হয়। ইমেল ক্লায়েন্টটি তার হ্যান্ডেল করতে পারা "সেরা" সংস্করণটি প্রদর্শন করবে (সাধারণত HTML)।- এটি স্বয়ংক্রিয়ভাবে একটি
multipart/alternative
MIME কাঠামো তৈরি করে।
সংযুক্তি পরিচালনা
ফাইল সংযুক্তি করা add_attachment()
ব্যবহার করে খুবই সহজ। আপনি যেকোনো ধরনের ফাইল সংযুক্ত করতে পারেন, এবং প্যাকেজটি উপযুক্ত MIME টাইপ এবং এনকোডিং (সাধারণত base64
) পরিচালনা করে।
from email.message import EmailMessage
from pathlib import Path
# Create dummy files for demonstration
Path('report.pdf').write_bytes(b'%PDF-1.4\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n2 0 obj<</Count 0>>endobj\nxref\n0 3\n0000000000 65535 f\n0000000009 00000 n\n0000000052 00000 n\ntrailer<</Size 3/Root 1 0 R>>startxref\n104\n%%EOF') # A very basic, invalid PDF placeholder
Path('logo.png').write_bytes(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0cIDAT\x08\x99c`\x00\x00\x00\x02\x00\x01\xe2!\x00\xa0\x00\x00\x00\x00IEND\xaeB`\x82') # A 1x1 transparent PNG placeholder
msg = EmailMessage()
msg['Subject'] = 'Important Document and Image'
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
msg.set_content('Please find the attached report and company logo.')
# Attach a PDF file
with open('report.pdf', 'rb') as f:
file_data = f.read()
msg.add_attachment(
file_data,
maintype='application',
subtype='pdf',
filename='Annual_Report_2024.pdf'
)
# Attach an image file
with open('logo.png', 'rb') as f:
image_data = f.read()
msg.add_attachment(
image_data,
maintype='image',
subtype='png',
filename='CompanyLogo.png'
)
print(msg.as_string())
# Clean up dummy files
Path('report.pdf').unlink()
Path('logo.png').unlink()
ব্যাখ্যা:
add_attachment()
ফাইলের কন্টেন্টের কাঁচা বাইট নেয়।maintype
এবংsubtype
MIME টাইপ নির্দিষ্ট করে (যেমন,application/pdf
,image/png
)। প্রাপকের ইমেল ক্লায়েন্টের জন্য সংযুক্তিটি সঠিকভাবে সনাক্ত এবং পরিচালনা করার জন্য এগুলি অত্যন্ত গুরুত্বপূর্ণ।filename
সেই নামটি প্রদান করে যার অধীনে সংযুক্তিটি প্রাপকের দ্বারা সংরক্ষিত হবে।- এটি স্বয়ংক্রিয়ভাবে একটি
multipart/mixed
কাঠামো সেট আপ করে।
মাল্টিপার্ট মেসেজ তৈরি করা
যখন আপনার কাছে HTML বডি, একটি প্লেইন টেক্সট ফলব্যাক এবং ইনলাইন ছবি বা সম্পর্কিত ফাইলসহ একটি বার্তা থাকে, তখন আপনার একটি আরও জটিল মাল্টিপার্ট কাঠামো প্রয়োজন। EmailMessage
ক্লাসটি add_related()
এবং add_alternative()
দিয়ে এটি বুদ্ধিমত্তার সাথে পরিচালনা করে।
একটি সাধারণ পরিস্থিতি হলো HTML-এর মধ্যে সরাসরি এম্বেড করা একটি ছবিসহ HTML ইমেল ("ইনলাইন" ছবি)। এটি multipart/related
ব্যবহার করে।
from email.message import EmailMessage
from pathlib import Path
# Create a dummy image file for demonstration (a 1x1 transparent PNG)
Path('banner.png').write_bytes(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0cIDAT\x08\x99c`\x00\x00\x00\x02\x00\x01\xe2!\x00\xa0\x00\x00\x00\x00IEND\xaeB`\x82')
msg = EmailMessage()
msg['Subject'] = 'Inline Image Example'
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
# Plain text version (fallback)
plain_text = 'Check out our amazing banner!\n\n[Image: Banner.png]\n\nVisit our site.'
msg.set_content(plain_text, subtype='plain') # Set initial plain text content
# HTML version (with CID for inline image)
html_content = """
<html>
<head></head>
<body>
<h1>Our Latest Offer!</h1>
<p>Dear Customer,</p>
<p>Don't miss out on our special global promotion:</p>
<img src="cid:my-banner-image" alt="Promotion Banner">
<p>Click <a href="http://www.example.com">here</a> to learn more.</p>
</body>
</html>
"""
msg.add_alternative(html_content, subtype='html') # Add HTML alternative
# Add the inline image (related content)
with open('banner.png', 'rb') as img_file:
image_data = img_file.read()
msg.add_related(
image_data,
maintype='image',
subtype='png',
cid='my-banner-image' # This CID matches the 'src' in HTML
)
print(msg.as_string())
# Clean up dummy file
Path('banner.png').unlink()
ব্যাখ্যা:
set_content()
প্রাথমিক বিষয়বস্তু স্থাপন করে (এখানে, প্লেইন টেক্সট)।add_alternative()
HTML সংস্করণ যোগ করে, একটিmultipart/alternative
কাঠামো তৈরি করে যা প্লেইন টেক্সট এবং HTML অংশগুলি ধারণ করে।add_related()
এমন কন্টেন্টের জন্য ব্যবহৃত হয় যা বার্তার অংশগুলির মধ্যে একটির সাথে "সম্পর্কিত", সাধারণত HTML-এ ইনলাইন ছবি। এটি একটিcid
(Content-ID) প্যারামিটার নেয়, যা পরে HTML<img src="cid:my-banner-image">
ট্যাগে রেফারেন্স করা হয়।- চূড়ান্ত কাঠামোটি হবে
multipart/mixed
(যদি বাহ্যিক সংযুক্তি থাকত) যা একটিmultipart/alternative
অংশ ধারণ করে, যা ফলস্বরূপ একটিmultipart/related
অংশ ধারণ করে।multipart/related
অংশটি HTML এবং ইনলাইন চিত্র ধারণ করে।EmailMessage
ক্লাস আপনার জন্য এই নেস্টিং জটিলতা পরিচালনা করে।
বিশ্বব্যাপী পৌঁছানোর জন্য এনকোডিং এবং ক্যারেক্টার সেট
আন্তর্জাতিক যোগাযোগের জন্য, সঠিক ক্যারেক্টার এনকোডিং অপরিহার্য। email
প্যাকেজ, ডিফল্টরূপে, UTF-8 ব্যবহারে অত্যন্ত দৃঢ়প্রতিজ্ঞ, যা বিশ্বজুড়ে বিভিন্ন ক্যারেক্টার সেট পরিচালনার জন্য সার্বজনীন মান।
from email.message import EmailMessage
msg = EmailMessage()
msg['Subject'] = 'Global Characters: こんにちは, Привет, नमस्ते'
msg['From'] = 'global_sender@example.com'
msg['To'] = 'global_recipient@example.com'
# Japanese, Russian, and Hindi characters
content = "This message contains diverse global characters:\n"
content += "こんにちは (Japanese)\n"
content += "Привет (Russian)\n"
content += "नमस्ते (Hindi)\n\n"
content += "The 'email' package handles UTF-8 gracefully."
msg.set_content(content)
print(msg.as_string())
ব্যাখ্যা:
- যখন
set_content()
একটি পাইথন স্ট্রিং গ্রহণ করে, তখন এটি স্বয়ংক্রিয়ভাবে এটিকে UTF-8 এ এনকোড করে এবংContent-Type: text/plain; charset="utf-8"
হেডার সেট করে। - যদি বিষয়বস্তুর প্রয়োজন হয় (যেমন, অনেক অ-ASCII অক্ষর থাকে), তবে এটি পুরানো ইমেল সিস্টেমের উপর নিরাপদ ট্রান্সমিশন নিশ্চিত করার জন্য
Content-Transfer-Encoding: quoted-printable
বাbase64
প্রয়োগ করতে পারে। প্যাকেজটি নির্বাচিত পলিসি অনুসারে এটি স্বয়ংক্রিয়ভাবে পরিচালনা করে।
কাস্টম হেডার এবং পলিসি
আপনি একটি ইমেলে যেকোনো কাস্টম হেডার যোগ করতে পারেন। পলিসি (email.policy
থেকে) নির্ধারণ করে যে কীভাবে বার্তাগুলি পরিচালনা করা হবে, যা হেডার এনকোডিং, লাইন এন্ডিং এবং ত্রুটি পরিচালনার মতো দিকগুলিকে প্রভাবিত করে। ডিফল্ট পলিসি সাধারণত ভাল, তবে আপনি কঠোর SMTP কমপ্লায়েন্সের জন্য `SMTP` বেছে নিতে পারেন বা কাস্টম পলিসি সংজ্ঞায়িত করতে পারেন।
from email.message import EmailMessage
from email import policy
msg = EmailMessage(policy=policy.SMTP)
msg['Subject'] = 'Email with Custom Header'
msg['From'] = 'info@example.org'
msg['To'] = 'user@example.org'
msg['X-Custom-Header'] = 'This is a custom value for tracking'
msg['Reply-To'] = 'support@example.org'
msg.set_content('This email demonstrates custom headers and policies.')
print(msg.as_string())
ব্যাখ্যা:
policy=policy.SMTP
ব্যবহার করা SMTP স্ট্যান্ডার্ডের সাথে কঠোর সম্মতি নিশ্চিত করে, যা ডেলিভারেবিলিটির জন্য গুরুত্বপূর্ণ হতে পারে।- কাস্টম হেডারগুলি স্ট্যান্ডার্ড হেডারের মতোই যোগ করা হয়। এগুলি প্রায়শই
X-
দিয়ে শুরু হয় যা নন-স্ট্যান্ডার্ড হেডার বোঝায়।
MIME মেসেজ পার্সিং: আগত ইমেল থেকে তথ্য নিষ্কাশন
পার্সিং এর মধ্যে কাঁচা ইমেল ডেটা (সাধারণত IMAP এর মাধ্যমে বা একটি ফাইল থেকে প্রাপ্ত) নিয়ে এটিকে একটি `EmailMessage` অবজেক্টে রূপান্তর করা জড়িত, যা আপনি সহজেই পরিদর্শন এবং পরিচালনা করতে পারেন।
লোড করা এবং প্রাথমিক পার্সিং
আপনি সাধারণত কাঁচা বাইট হিসাবে ইমেল পাবেন। এর জন্য email.parser.BytesParser
(বা সুবিধাজনক ফাংশন email.message_from_bytes()
) ব্যবহৃত হয়।
from email.parser import BytesParser
from email.policy import default
raw_email_bytes = b"""
From: sender@example.com
To: recipient@example.com
Subject: Test Email with Basic Headers
Date: Mon, 1 Jan 2024 10:00:00 +0000
Content-Type: text/plain; charset="utf-8"
This is the body of the email.
It's a simple test.
"""
# Using BytesParser
parser = BytesParser(policy=default)
msg = parser.parsebytes(raw_email_bytes)
# Or using the convenience function
# from email import message_from_bytes
# msg = message_from_bytes(raw_email_bytes, policy=default)
print(f"Subject: {msg['subject']}")
print(f"From: {msg['from']}")
print(f"Content-Type: {msg['Content-Type']}")
ব্যাখ্যা:
BytesParser
কাঁচা বাইট ডেটা (যেভাবে ইমেল প্রেরণ করা হয়) নেয় এবং একটিEmailMessage
অবজেক্ট প্রদান করে।policy=default
পার্সিং নিয়মগুলি নির্দিষ্ট করে।
হেডার অ্যাক্সেস করা
হেডারগুলি ডিকশনারির মতো কী-এর মাধ্যমে সহজেই অ্যাক্সেসযোগ্য। প্যাকেজটি স্বয়ংক্রিয়ভাবে এনকোড করা হেডারগুলির ডিকোডিং পরিচালনা করে (যেমন, আন্তর্জাতিক অক্ষরসহ সাবজেক্ট)।
# ... (using the 'msg' object from the previous parsing example)
print(f"Date: {msg['date']}")
print(f"Message ID: {msg['Message-ID'] if 'Message-ID' in msg else 'N/A'}")
# Handling multiple headers (e.g., 'Received' headers)
# from email.message import EmailMessage # If not imported yet
# from email import message_from_string # For a quick string example
multi_header_email = message_from_string(
"""
From: a@example.com
To: b@example.com
Subject: Multi-header Test
Received: from client.example.com (client.example.com [192.168.1.100])
by server.example.com (Postfix) with ESMTP id 123456789
for <b@example.com>; Mon, 1 Jan 2024 10:00:00 +0000 (GMT)
Received: from mx.another.com (mx.another.com [192.168.1.101])
by server.example.com (Postfix) with ESMTP id 987654321
for <b@example.com>; Mon, 1 Jan 2024 09:59:00 +0000 (GMT)
Body content here.
"""
)
received_headers = multi_header_email.get_all('received')
if received_headers:
print("\nReceived Headers:")
for header in received_headers:
print(f"- {header}")
ব্যাখ্যা:
- একটি হেডার অ্যাক্সেস করলে তার মান একটি স্ট্রিং হিসাবে ফেরত আসে।
get_all('header-name')
সেই সব হেডারের জন্য উপযোগী যা একাধিকবার প্রদর্শিত হতে পারে (যেমনReceived
)।- প্যাকেজটি হেডার ডিকোডিং পরিচালনা করে, তাই
Subject: =?utf-8?Q?Global_Characters:_=E3=81=93=E3=82=93=E3=81=AB=E3=81=A1=E3=81=AF?=
এর মতো মানগুলি স্বয়ংক্রিয়ভাবে পঠনযোগ্য স্ট্রিং-এ রূপান্তরিত হয়।
বডি কন্টেন্ট নিষ্কাশন
প্রকৃত মেসেজ বডি নিষ্কাশন করার জন্য বার্তাটি মাল্টিপার্ট কিনা তা পরীক্ষা করা প্রয়োজন। মাল্টিপার্ট বার্তাগুলির জন্য, আপনি এর অংশগুলির মধ্যে দিয়ে ইটারেট করবেন।
from email.message import EmailMessage
from email import message_from_string
multipart_email_raw = """
From: multi@example.com
To: user@example.com
Subject: Test Multipart Email
Content-Type: multipart/alternative; boundary="_----------=_12345"
--_----------=_12345
Content-Type: text/plain; charset="utf-8"
Hello from the plain text part!
--_----------=_12345
Content-Type: text/html; charset="utf-8"
<html>
<body>
<h1>Hello from the HTML part!</h1>
<p>This is a <strong>rich text</strong> email.</p>
</body>
</html>
--_----------=_12345--
"""
msg = message_from_string(multipart_email_raw)
if msg.is_multipart():
print("\n--- Multipart Email Body ---")
for part in msg.iter_parts():
content_type = part.get_content_type()
charset = part.get_content_charset() or 'utf-8' # Default to utf-8 if not specified
payload = part.get_payload(decode=True) # Decode payload bytes
try:
decoded_content = payload.decode(charset)
print(f"Content-Type: {content_type}, Charset: {charset}\nContent:\n{decoded_content}\n")
except UnicodeDecodeError:
print(f"Content-Type: {content_type}, Charset: {charset}\nContent: (Binary or undecodable data)\n")
# Handle binary data, or attempt a fallback encoding
else:
print("\n--- Single Part Email Body ---")
charset = msg.get_content_charset() or 'utf-8'
payload = msg.get_payload(decode=True)
try:
decoded_content = payload.decode(charset)
print(f"Content-Type: {msg.get_content_type()}, Charset: {charset}\nContent:\n{decoded_content}\n")
except UnicodeDecodeError:
print(f"Content: (Binary or undecodable data)\n")
ব্যাখ্যা:
is_multipart()
নির্ধারণ করে যে ইমেলটিতে একাধিক অংশ আছে কিনা।iter_parts()
একটি মাল্টিপার্ট বার্তার সমস্ত উপ-অংশের মধ্যে দিয়ে ইটারেট করে।get_content_type()
সম্পূর্ণ MIME টাইপ প্রদান করে (যেমন,text/plain
)।get_content_charset()
Content-Type
হেডার থেকে ক্যারেক্টার সেট বের করে।get_payload(decode=True)
অত্যন্ত গুরুত্বপূর্ণ: এটি *ডিকোড করা* কন্টেন্টকে বাইট হিসাবে প্রদান করে। তারপর আপনাকে একটি পাইথন স্ট্রিং পেতে সঠিক ক্যারেক্টার সেট ব্যবহার করে এই বাইটগুলিকে.decode()
করতে হবে।
পার্সিং করার সময় সংযুক্তি পরিচালনা
সংযুক্তিগুলিও একটি মাল্টিপার্ট বার্তার অংশ। আপনি তাদের Content-Disposition
হেডার ব্যবহার করে সনাক্ত করতে এবং তাদের ডিকোড করা পেলোড সংরক্ষণ করতে পারেন।
from email.message import EmailMessage
from email import message_from_string
import os
# Example email with a simple attachment
email_with_attachment = """
From: attach@example.com
To: user@example.com
Subject: Document Attached
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="_----------=_XYZ"
--_----------=_XYZ
Content-Type: text/plain; charset="utf-8"
Here is your requested document.
--_----------=_XYZ
Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="document.pdf"
JVBERi0xLjQKMSAwIG9iagpbL1BERi9UZXh0L0ltYWdlQy9JbWFnZUkvSW1hZ0VCXQplbmRvYmoK
--_----------=_XYZ--
"""
msg = message_from_string(email_with_attachment)
output_dir = 'parsed_attachments'
os.makedirs(output_dir, exist_ok=True)
print("\n--- Processing Attachments ---")
for part in msg.iter_attachments():
filename = part.get_filename()
if filename:
filepath = os.path.join(output_dir, filename)
try:
with open(filepath, 'wb') as f:
f.write(part.get_payload(decode=True))
print(f"Saved attachment: {filepath} (Type: {part.get_content_type()})")
except Exception as e:
print(f"Error saving {filename}: {e}")
else:
print(f"Found an attachment without a filename (Content-Type: {part.get_content_type()})")
# Clean up the output directory
# import shutil
# shutil.rmtree(output_dir)
ব্যাখ্যা:
iter_attachments()
বিশেষভাবে সেই অংশগুলি প্রদান করে যা সংযুক্তি হওয়ার সম্ভাবনা বেশি (অর্থাৎ, একটিContent-Disposition: attachment
হেডার আছে বা অন্যথায় শ্রেণীবদ্ধ নয়)।get_filename()
Content-Disposition
হেডার থেকে ফাইলের নাম বের করে।part.get_payload(decode=True)
সংযুক্তির কাঁচা বাইনারি বিষয়বস্তু পুনরুদ্ধার করে, যা ইতিমধ্যেbase64
বাquoted-printable
থেকে ডিকোড করা হয়েছে।
এনকোডিং এবং ক্যারেক্টার সেট ডিকোড করা
email
প্যাকেজটি get_payload(decode=True)
কল করার সময় সাধারণ ট্রান্সফার এনকোডিংগুলি (যেমন base64
, quoted-printable
) স্বয়ংক্রিয়ভাবে ডিকোড করার একটি চমৎকার কাজ করে। টেক্সট কন্টেন্টের জন্য, এটি Content-Type
হেডারে নির্দিষ্ট charset
ব্যবহার করার চেষ্টা করে। যদি কোনো ক্যারেক্টার সেট নির্দিষ্ট না করা হয় বা এটি অবৈধ হয়, তবে আপনাকে এটি সুন্দরভাবে পরিচালনা করতে হতে পারে।
from email.message import EmailMessage
from email import message_from_string
# Example with a potentially problematic charset
email_latin1 = """
From: legacy@example.com
To: new_system@example.com
Subject: Special characters: àéíóú
Content-Type: text/plain; charset="iso-8859-1"
This message contains Latin-1 characters: àéíóú
"""
msg = message_from_string(email_latin1)
if msg.is_multipart():
for part in msg.iter_parts():
payload = part.get_payload(decode=True)
charset = part.get_content_charset() or 'utf-8'
try:
print(f"Decoded (Charset: {charset}): {payload.decode(charset)}")
except UnicodeDecodeError:
print(f"Failed to decode with {charset}. Trying fallback...")
# Fallback to a common charset or 'latin-1' if expecting it
print(f"Decoded (Fallback Latin-1): {payload.decode('latin-1', errors='replace')}")
else:
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset() or 'utf-8'
try:
print(f"Decoded (Charset: {charset}): {payload.decode(charset)}")
except UnicodeDecodeError:
print(f"Failed to decode with {charset}. Trying fallback...")
print(f"Decoded (Fallback Latin-1): {payload.decode('latin-1', errors='replace')}")
ব্যাখ্যা:
- সর্বদা
Content-Type
হেডারে নির্দিষ্ট করা ক্যারেক্টার সেট ব্যবহার করার চেষ্টা করুন। - দৃঢ়তার জন্য একটি
try-except UnicodeDecodeError
ব্লক ব্যবহার করুন, বিশেষ করে যখন বিভিন্ন এবং সম্ভাব্য নন-স্ট্যান্ডার্ড উৎস থেকে আসা ইমেলের সাথে কাজ করছেন। errors='replace'
বাerrors='ignore'
.decode()
এর সাথে ব্যবহার করা যেতে পারে সেই সব অক্ষর পরিচালনা করতে যা টার্গেট এনকোডিংয়ে ম্যাপ করা যায় না, যা ক্র্যাশ প্রতিরোধ করে।
উন্নত পার্সিং পরিস্থিতি
বাস্তব-বিশ্বের ইমেলগুলি অত্যন্ত জটিল হতে পারে, যাতে নেস্টেড মাল্টিপার্ট কাঠামো থাকে। email
প্যাকেজের রিকার্সিভ প্রকৃতি এগুলিকে নেভিগেট করা সহজ করে তোলে। আপনি গভীর নেস্টেড বার্তাগুলি অতিক্রম করতে is_multipart()
এবং iter_parts()
একত্রিত করতে পারেন।
from email.message import EmailMessage
from email import message_from_string
def parse_email_part(part, indent=0):
prefix = " " * indent
content_type = part.get_content_type()
charset = part.get_content_charset() or 'N/A'
print(f"{prefix}Part Type: {content_type}, Charset: {charset}")
if part.is_multipart():
for subpart in part.iter_parts():
parse_email_part(subpart, indent + 1)
elif part.get_filename(): # It's an attachment
print(f"{prefix} Attachment: {part.get_filename()} (Size: {len(part.get_payload(decode=True))} bytes)")
else: # It's a regular text/html body part
payload = part.get_payload(decode=True)
try:
decoded_content = payload.decode(charset)
# print(f"{prefix} Content (first 100 chars): {decoded_content[:100]}...") # For brevity
except UnicodeDecodeError:
print(f"{prefix} Content: (Binary or undecodable text)")
complex_email_raw = """
From: complex@example.com
To: receiver@example.com
Subject: Complex Email with HTML, Plain, and Attachment
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="outer_boundary"
--outer_boundary
Content-Type: multipart/alternative; boundary="inner_boundary"
--inner_boundary
Content-Type: text/plain; charset="utf-8"
Plain text content.
--inner_boundary
Content-Type: text/html; charset="utf-8"
<html><body><h2>HTML Content</h2></body></html>
--inner_boundary--
--outer_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="data.bin"
SGVsbG8gV29ybGQh
--outer_boundary--
"""
msg = message_from_string(complex_email_raw)
print("\n--- Traversing Complex Email Structure ---")
parse_email_part(msg)
ব্যাখ্যা:
- রিকার্সিভ ফাংশন
parse_email_part
দেখায় কিভাবে সম্পূর্ণ মেসেজ ট্রি এর মধ্যে দিয়ে যেতে হয়, প্রতিটি স্তরে মাল্টিপার্ট অংশ, সংযুক্তি এবং বডি কন্টেন্ট সনাক্ত করতে হয়। - এই প্যাটার্নটি গভীর নেস্টেড ইমেল থেকে নির্দিষ্ট ধরণের কন্টেন্ট নিষ্কাশন করার জন্য অত্যন্ত নমনীয়।
নির্মাণ বনাম পার্সিং: একটি তুলনামূলক দৃষ্টিভঙ্গি
যদিও স্বতন্ত্র ক্রিয়াকলাপ, নির্মাণ এবং পার্সিং একই মুদ্রার দুটি দিক: MIME বার্তা পরিচালনা। একটি বোঝা অনিবার্যভাবে অন্যটিকে সাহায্য করে।
নির্মাণ (পাঠানো):
- ফোকাস: হেডার, বিষয়বস্তু এবং সংযুক্তিগুলিকে একটি মান-সম্মত MIME কাঠামোতে সঠিকভাবে একত্রিত করা।
- প্রাথমিক টুল:
email.message.EmailMessage
এবং এর পদ্ধতি যেমনset_content()
,add_attachment()
,add_alternative()
,add_related()
। - মূল চ্যালেঞ্জ: সঠিক MIME টাইপ, ক্যারেক্টার সেট (বিশেষ করে বিশ্বব্যাপী সমর্থনের জন্য UTF-8), `Content-Transfer-Encoding` এবং সঠিক হেডার ফরম্যাটিং নিশ্চিত করা। ভুল পদক্ষেপের ফলে ইমেলগুলি সঠিকভাবে প্রদর্শিত না হওয়া, সংযুক্তিগুলি নষ্ট হয়ে যাওয়া বা বার্তাগুলি স্প্যাম হিসাবে চিহ্নিত হতে পারে।
পার্সিং (গ্রহণ করা):
- ফোকাস: একটি কাঁচা ইমেল বাইট স্ট্রিমকে তার উপাদান অংশে বিভক্ত করা, নির্দিষ্ট হেডার, বডি কন্টেন্ট এবং সংযুক্তি নিষ্কাশন করা।
- প্রাথমিক টুল:
email.parser.BytesParser
বাemail.message_from_bytes()
, তারপর প্রাপ্তEmailMessage
অবজেক্টটিকেis_multipart()
,iter_parts()
,get_payload()
,get_filename()
এর মতো পদ্ধতি এবং হেডার অ্যাক্সেসের মাধ্যমে নেভিগেট করা। - মূল চ্যালেঞ্জ: ত্রুটিপূর্ণ ইমেল পরিচালনা করা, ক্যারেক্টার এনকোডিং সঠিকভাবে সনাক্ত করা (বিশেষ করে যখন অস্পষ্ট), অনুপস্থিত হেডারগুলির সাথে মোকাবিলা করা এবং বিভিন্ন MIME কাঠামো থেকে দৃঢ়ভাবে ডেটা নিষ্কাশন করা।
`EmailMessage` ব্যবহার করে আপনি যে বার্তাটি তৈরি করেন তা `BytesParser` দ্বারা নিখুঁতভাবে পার্সযোগ্য হওয়া উচিত। একইভাবে, পার্সিংয়ের সময় উৎপাদিত MIME কাঠামো বোঝা আপনাকে নিজে জটিল বার্তা তৈরি করার অন্তর্দৃষ্টি দেয়।
পাইথন দিয়ে বিশ্বব্যাপী ইমেল পরিচালনার জন্য সেরা অনুশীলন
যে অ্যাপ্লিকেশনগুলি একটি বিশ্বব্যাপী দর্শকের সাথে ইন্টারঅ্যাক্ট করে বা বিভিন্ন ইমেল উৎস পরিচালনা করে, তাদের জন্য এই সেরা অনুশীলনগুলি বিবেচনা করুন:
- UTF-8 কে স্ট্যান্ডার্ড করুন: সর্বদা সমস্ত টেক্সট কন্টেন্টের জন্য UTF-8 ব্যবহার করুন, নির্মাণ এবং পার্সিং উভয় ক্ষেত্রেই। এটি ক্যারেক্টার এনকোডিংয়ের জন্য বিশ্বব্যাপী মান এবং মোজিবেকে (বিকৃত টেক্সট) এড়িয়ে চলে।
- ইমেল ঠিকানা যাচাই করুন: পাঠানোর আগে, ডেলিভারেবিলিটি নিশ্চিত করতে প্রাপকের ইমেল ঠিকানা যাচাই করুন। পার্সিংয়ের সময়, `From`, `To`, বা `Cc` হেডারে সম্ভাব্য অবৈধ বা ত্রুটিপূর্ণ ঠিকানাগুলির জন্য প্রস্তুত থাকুন।
- কঠোরভাবে পরীক্ষা করুন: বিভিন্ন ইমেল ক্লায়েন্ট (Gmail, Outlook, Apple Mail, Thunderbird) এবং প্ল্যাটফর্মে আপনার ইমেল নির্মাণ পরীক্ষা করুন যাতে HTML এবং সংযুক্তির সামঞ্জস্যপূর্ণ রেন্ডারিং নিশ্চিত হয়। পার্সিংয়ের জন্য, অস্বাভাবিক এনকোডিং, অনুপস্থিত হেডার বা জটিল নেস্টেড কাঠামোসহ বিভিন্ন নমুনার ইমেল দিয়ে পরীক্ষা করুন।
- পার্স করা ইনপুট স্যানিটাইজ করুন: আগত ইমেল থেকে নিষ্কাশিত বিষয়বস্তুকে সর্বদা অবিশ্বস্ত হিসাবে বিবেচনা করুন। যদি আপনি এটি একটি ওয়েব অ্যাপ্লিকেশনে প্রদর্শন করেন তবে XSS আক্রমণ প্রতিরোধ করতে HTML বিষয়বস্তু স্যানিটাইজ করুন। ফাইল সংরক্ষণ করার সময় পাথ ট্রাভার্সাল বা অন্যান্য নিরাপত্তা দুর্বলতা প্রতিরোধ করতে সংযুক্তির ফাইলের নাম এবং ধরণ যাচাই করুন।
- শক্তিশালী ত্রুটি হ্যান্ডলিং: পেলোড ডিকোড করার সময় বা সম্ভাব্য অনুপস্থিত হেডার অ্যাক্সেস করার সময় ব্যাপক
try-except
ব্লক প্রয়োগ করুন।UnicodeDecodeError
বাKeyError
সুন্দরভাবে পরিচালনা করুন। - বড় সংযুক্তি পরিচালনা করুন: সংযুক্তি আকারের বিষয়ে সচেতন থাকুন, নির্মাণ (মেল সার্ভারের সীমা অতিক্রম এড়াতে) এবং পার্সিং (অতিরিক্ত মেমরি ব্যবহার বা ডিস্ক স্পেস খরচ প্রতিরোধ করতে) উভয় ক্ষেত্রেই। আপনার সিস্টেম দ্বারা সমর্থিত হলে বড় সংযুক্তিগুলি স্ট্রিম করার কথা বিবেচনা করুন।
email.policy
ব্যবহার করুন: গুরুতর অ্যাপ্লিকেশনগুলির জন্য, ইমেল স্ট্যান্ডার্ডের সাথে কঠোর সম্মতি নিশ্চিত করতে স্পষ্টভাবে একটি `email.policy` (যেমন, `policy.SMTP`) বেছে নিন, যা ডেলিভারেবিলিটি এবং ইন্টারঅপারেবিলিটিকে প্রভাবিত করতে পারে।- মেটাডেটা সংরক্ষণ: পার্সিং করার সময়, সিদ্ধান্ত নিন কোন মেটাডেটা (হেডার, মূল বাউন্ডারি স্ট্রিং) সংরক্ষণ করা গুরুত্বপূর্ণ, বিশেষ করে যদি আপনি একটি মেল আর্কাইভাল বা ফরওয়ার্ডিং সিস্টেম তৈরি করেন।
উপসংহার
পাইথনের email
প্যাকেজটি যে কেউ প্রোগ্রামগতভাবে ইমেলের সাথে ইন্টারঅ্যাক্ট করতে চান তাদের জন্য একটি অবিশ্বাস্যভাবে শক্তিশালী এবং নমনীয় লাইব্রেরি। MIME বার্তাগুলির নির্মাণ এবং আগত ইমেলগুলির শক্তিশালী পার্সিং উভয় ক্ষেত্রেই দক্ষতা অর্জনের মাধ্যমে, আপনি অত্যাধুনিক ইমেল অটোমেশন সিস্টেম তৈরি করতে, ইমেল ক্লায়েন্ট তৈরি করতে, ইমেল ডেটা বিশ্লেষণ করতে এবং কার্যত যেকোনো অ্যাপ্লিকেশনে ইমেল কার্যকারিতা একীভূত করার ক্ষমতা আনলক করেন।
প্যাকেজটি MIME-এর অন্তর্নিহিত জটিলতাগুলি যত্নসহকারে পরিচালনা করে, যা ডেভেলপারদের তাদের ইমেল ইন্টারঅ্যাকশনের বিষয়বস্তু এবং যুক্তির উপর ফোকাস করতে দেয়। আপনি বিশ্বব্যাপী দর্শকদের কাছে ব্যক্তিগতকৃত নিউজলেটার পাঠাচ্ছেন বা স্বয়ংক্রিয় সিস্টেম রিপোর্ট থেকে গুরুত্বপূর্ণ ডেটা নিষ্কাশন করছেন, email
প্যাকেজের গভীর উপলব্ধি নির্ভরযোগ্য, আন্তঃক্রিয়াশীল এবং বিশ্বব্যাপী-সচেতন ইমেল সমাধান তৈরিতে অমূল্য প্রমাণিত হবে।