基于Pandas数据帧匹配值并迭代触发Outlook邮件发送
Solution for Automated Email Sending from Pandas DataFrame with Keyword Matching
I see where your code is getting stuck—let's fix it to properly match keywords in your CSV, extract the right row data, and trigger emails correctly. Here's the revised code that implements your required logic:
import win32com.client as win32 import psutil import os import subprocess import pandas as pd import time # Read CSV once (no need to read twice!) filename = "users\\cmbp\\p4e\\test_rad_reports.csv" df = pd.read_csv(filename, usecols=['reason', 'notes', 'email']) def send_notification(recipient_email, subject, body): """Send email via Outlook with provided details""" outlook = win32.Dispatch('outlook.application') mail = outlook.CreateItem(0) mail.To = recipient_email mail.Subject = subject mail.Body = body mail.Send() # Fixed syntax and removed unnecessary loop def open_outlook(): """Launch Outlook if it's not running""" try: # Use subprocess.call to avoid duplicate launches subprocess.call(['C:\\Program Files\\Microsoft Office\\Office16\\Outlook.exe']) except Exception as e: print(f"Outlook didn't open successfully: {str(e)}") def check_outlook(): """Check if Outlook is running; launch if not, then return Outlook instance""" outlook_running = False for item in psutil.pids(): try: p = psutil.Process(item) if p.name().upper() == "OUTLOOK.EXE": outlook_running = True break except (psutil.NoSuchProcess, psutil.AccessDenied): continue # Skip processes we can't access if not outlook_running: open_outlook() # Give Outlook a moment to launch before sending emails time.sleep(2) def process_csv_and_send_emails(): """Iterate through DataFrame, match keywords, and send notifications""" # Filter rows where 'reason' column contains 'reasona' (adjust match rules as needed) matching_rows = df[df['reason'].str.contains('reasona', case=False, na=False)] for _, row in matching_rows.iterrows(): # Extract values from the matched row into variables recipient = row['email'] reason_text = row['reason'] notes_text = row['notes'] # Customize email content email_subject = f"Notification for Reason: {reason_text}" email_body = f"Reason: {reason_text}\nNotes: {notes_text}" # Ensure Outlook is running before sending check_outlook() # Trigger email sending with extracted data send_notification(recipient, email_subject, email_body) print(f"Email sent to {recipient} successfully!") # Run the main process if __name__ == "__main__": process_csv_and_send_emails()
Key Improvements & Explanations:
- Single CSV Read: We read the CSV once into
dfinstead of twice—cleaner and more efficient. - Proper Row Matching: Instead of looping over column names, we use
df['reason'].str.contains()to filter rows with your target keyword. Thecase=Falseflag makes the match case-insensitive (remove it if you need exact case matching). - Parameterized Email Function:
send_notificationnow accepts recipient, subject, and body as parameters, avoiding messy global variable dependencies and making the function reusable. - Fixed Outlook Check Logic: We initialize
outlook_runningupfront and handle edge cases like inaccessible processes. A short delay after launching Outlook ensures it's ready to send emails. - Clear Function Separation: Each function has a single job—processing the CSV, managing Outlook state, or sending emails—making the code easier to debug and modify.
- Error Handling: Added basic exception catching to report issues with Outlook launches or process checks.
Quick Customization Tips:
- Adjust the keyword match in
df['reason'].str.contains()to your exact target (e.g., use== 'reasona'for an exact match). - Modify the
email_subjectandemail_bodylines to fit your desired notification format. - Double-check the Outlook executable path in
open_outlook()if your Office version uses a different directory.
内容的提问来源于stack exchange,提问作者Philalethes
相关产品推荐
相关产品推荐

