Jenkins:使用 win32 通过 python 发送邮件

问题描述 投票:0回答:1

在此处输入图像描述我在 jenkins 中调用 python 脚本以使用 win32 发送电子邮件,该脚本在从命令窗口运行时完美运行,但在 jenkins 管道中使用时抛出错误。

import win32com.client as win32
outlook=win32.Dispatch('outlook.application')
mail=outlook.CreateItem(0)
mail.To='[email protected]'
mail.Subject="Test Mail"
mail.HTMLBody="Hiii, This is just a test mail."
mail.Send()

错误:IDispatch = pythoncom.connect(IDispatch) pywintypes.com_error:(-2147221021,'操作不可用',无,无)

python email jenkins winapi
1个回答
0
投票
    import win32com.client as win32
    import pandas as pd
    import datetime
    import time
    
    # Outlook instance
    outlook = win32.Dispatch("Outlook.Application")
    namespace = outlook.GetNamespace("MAPI")
    inbox = namespace.GetDefaultFolder(6)  # 6 refers to the Inbox folder
    
    # Function to fetch emails from the inbox based on multiple subjects
    def fetch_emails(subject_filters=None, category_filter=None):
        messages = inbox.Items
        messages.Sort("[ReceivedTime]", True)  # Sort by received time, descending
        filtered_emails = []
    
        for message in messages:
            # Check if the email subject matches any of the subjects in the filter list
            if subject_filters and not any(subject in message.Subject for subject in subject_filters):
                continue
            if category_filter and category_filter not in message.Categories:
                continue
            
            email_details = {
                'Subject': message.Subject,
                'ReceivedTime': message.ReceivedTime
            }
            filtered_emails.append(email_details)
        
        return filtered_emails
    
    # Function to highlight missing data in the DataFrame
    def highlight_missing(val):
        color = 'red' if pd.isnull(val) or val == '' else ''
        return f'background-color: {color}'
    
    # Function to create a DataFrame from the list of emails
    def create_dataframe(filtered_emails, expected_emails):
        df = pd.DataFrame(filtered_emails)
        
        # Create a list of missing emails
        missing_emails = [email for email in expected_emails if email not in [e['Subject'] for e in filtered_emails]]
        
        # Add missing emails to the dataframe as absent
        for missing in missing_emails:
            df = df.append({'Subject': missing, 'ReceivedTime': 'No email found'}, ignore_index=True)
        
        # Order by received time in ascending order
        df['ReceivedTime'] = pd.to_datetime(df['ReceivedTime'], errors='coerce')
        df = df.sort_values(by='ReceivedTime', ascending=True)
        
        # Highlight missing rows (if subject or received time is missing)
        df_style = df.style.applymap(highlight_missing, subset=['Subject', 'ReceivedTime'])
        
        return df_style
    
    # Function to send the email with DataFrame as content using Outlook's win32 Dispatch
    def send_email_with_dataframe(df, to_email):
        # Convert dataframe to HTML table (using the pandas 'to_html' function)
        html_table = df.render()  # Render the styled DataFrame to HTML
        
        # Create the email
        mail = outlook.CreateItem(0)  # 0 refers to a Mail Item
        mail.Subject = "Automated Daily Email Report"
        mail.To = to_email  # The recipient email address
        
        # Create the email body with the DataFrame HTML
        mail.HTMLBody = f"<html><body><h2>Email Report</h2>{html_table}</body></html>"
        
        # Send the email
        mail.Sensitivity = 3  # Set sensitivity level (3 is 'Private')
        mail.Send()  # Send the email
        print("Email sent successfully using Outlook.")
    
    # Function to check emails and take actions based on time
    def check_emails():
        current_time = datetime.datetime.now()
        
        emails = []  # Initialize an empty list to store emails
        
        # Define subject lists for each email type (you can manually update these lists)
        subject_type1 = ["Subject 1a", "Subject 1b", "Subject 1c"]  # Update these subjects for Type 1 emails
        subject_type2 = ["Subject 2a", "Subject 2b"]  # Update these subjects for Type 2 emails
        subject_type3 = ["Subject 3a", "Subject 3b", "Subject 3c"]  # Update these subjects for Type 3 emails
        
        # Check for Type 1 emails (every day at 9:30 AM, 4 PM, 6 PM, 8 PM)
        if current_time.hour == 9 and current_time.minute == 30:
            emails = fetch_emails(subject_filters=subject_type1)
            df = create_dataframe(emails, subject_type1)
            send_email_with_dataframe(df, '[email protected]')  # Replace with the recipient's email
    
        # Check for Type 2 emails (every Monday at 4 PM)
        if current_time.weekday() == 0 and current_time.hour == 16:  # Monday
            emails = fetch_emails(subject_filters=subject_type2)
            df = create_dataframe(emails, subject_type2)
            send_email_with_dataframe(df, '[email protected]')  # Replace with the recipient's email
    
        # Check for Type 3 emails (every day at 4 PM)
        if current_time.hour == 16 and current_time.minute == 0:
            emails = fetch_emails(subject_filters=subject_type3)
            df = create_dataframe(emails, subject_type3)
            send_email_with_dataframe(df, '[email protected]')  # Replace with the recipient's email
    
    # Main function to run the scheduled checks
    def main():
        while True:
            check_emails()
            time.sleep(60)  # Check every minute to see if it's time to run a check
    
    if __name__ == "__main__":
        main()
        enter code here









Explanation of Changes:
Creating the DataFrame: The create_dataframe function now creates the DataFrame with Subject and ReceivedTime columns, and it handles missing emails.

Missing emails will be added with "No email found" in the ReceivedTime column.
Pandas Styling: We use the style.applymap() function to highlight missing data in the DataFrame, specifically the rows where Subject or ReceivedTime is missing.

Convert to HTML: We use the df.render() method to convert the DataFrame to HTML, which allows you to send the DataFrame directly in the email body.

Sending the Email: The send_email_with_dataframe function sends the DataFrame as HTML in the email body. This avoids manually creating an HTML table, as we are leveraging Pandas' ability to convert the DataFrame to HTML.

Example Output in the Email:
The email will contain a Pandas DataFrame rendered as an HTML table with the following:

Only the Subject and ReceivedTime.
Rows ordered by ReceivedTime in ascending order.
Missing emails will be displayed with "No email found" in the ReceivedTime column, and these rows will be highlighted in red.



Key Points:
The missing emails will be highlighted in red.
The table will be rendered using Pandas DataFrame.
The email body will contain the DataFrame directly as an HTML table.







with html body


    import win32com.client as win32
    import pandas as pd
    import datetime
    import time
    
    # Outlook instance
    outlook = win32.Dispatch("Outlook.Application")
    namespace = outlook.GetNamespace("MAPI")
    inbox = namespace.GetDefaultFolder(6)  # 6 refers to the Inbox folder
    
    # Function to fetch emails from the inbox based on multiple subjects
    def fetch_emails(subject_filters=None, category_filter=None):
        messages = inbox.Items
        messages.Sort("[ReceivedTime]", True)  # Sort by received time, descending
        filtered_emails = []
    
        for message in messages:
            # Check if the email subject matches any of the subjects in the filter list
            if subject_filters and not any(subject in message.Subject for subject in subject_filters):
                continue
            if category_filter and category_filter not in message.Categories:
                continue
            
            email_details = {
                'Subject': message.Subject,
                'ReceivedTime': message.ReceivedTime
            }
            filtered_emails.append(email_details)
        
        return filtered_emails
    
    # Function to highlight missing data in the DataFrame
    def highlight_missing(val):
        color = 'red' if pd.isnull(val) or val == '' else ''
        return f'background-color: {color}'
    
    # Function to create a DataFrame from the list of emails
    def create_dataframe(filtered_emails, expected_emails):
        df = pd.DataFrame(filtered_emails)
        
        # Create a list of missing emails
        missing_emails = [email for email in expected_emails if email not in [e['Subject'] for e in filtered_emails]]
        
        # Add missing emails to the dataframe as absent
        for missing in missing_emails:
            df = df.append({'Subject': missing, 'ReceivedTime': 'No email found'}, ignore_index=True)
        
        # Order by received time in ascending order
        df['ReceivedTime'] = pd.to_datetime(df['ReceivedTime'], errors='coerce')
        df = df.sort_values(by='ReceivedTime', ascending=True)
        
        # Highlight missing rows (if subject or received time is missing)
        df_style = df.style.applymap(highlight_missing, subset=['Subject', 'ReceivedTime'])
        return df_style
    
    # Function to send the email with DataFrame as content using Outlook's win32 Dispatch
    def send_email_with_dataframe(df, to_email):
        # Convert dataframe to HTML table
        html_table = df.render()  # Render the styled DataFrame to HTML
        
        # Create the email
        mail = outlook.CreateItem(0)  # 0 refers to a Mail Item
        mail.Subject = "Automated Daily Email Report"
        mail.To = to_email  # The recipient email address
        
        # Create the email body with the DataFrame HTML
        mail.HTMLBody = f"<html><body><h2>Email Report</h2>{html_table}</body></html>"
        
        # Send the email
        mail.Sensitivity = 3  # Set sensitivity level (3 is 'Private')
        mail.Send()  # Send the email
        print("Email sent successfully using Outlook.")
    
    # Function to check emails and take actions based on time
    def check_emails():
        current_time = datetime.datetime.now()
        
        emails = []  # Initialize an empty list to store emails
        
        # Define subject lists for each email type (you can manually update these lists)
        subject_type1 = ["Subject 1a", "Subject 1b", "Subject 1c"]  # Update these subjects for Type 1 emails
        subject_type2 = ["Subject 2a", "Subject 2b"]  # Update these subjects for Type 2 emails
        subject_type3 = ["Subject 3a", "Subject 3b", "Subject 3c"]  # Update these subjects for Type 3 emails
        
        # Check for Type 1 emails (every day at 9:30 AM, 4 PM, 6 PM, 8 PM)
        if current_time.hour == 9 and current_time.minute == 30:
            emails = fetch_emails(subject_filters=subject_type1)
            df = create_dataframe(emails, subject_type1)
            send_email_with_dataframe(df, '[email protected]')  # Replace with the recipient's email
    
        # Check for Type 2 emails (every Monday at 4 PM)
        if current_time.weekday() == 0 and current_time.hour == 16:  # Monday
            emails = fetch_emails(subject_filters=subject_type2)
            df = create_dataframe(emails, subject_type2)
            send_email_with_dataframe(df, '[email protected]')  # Replace with the recipient's email
    
        # Check for Type 3 emails (every day at 4 PM)
        if current_time.hour == 16 and current_time.minute == 0:
            emails = fetch_emails(subject_filters=subject_type3)
            df = create_dataframe(emails, subject_type3)
            send_email_with_dataframe(df, '[email protected]')  # Replace with the recipient's email
    
    # Main function to run the scheduled checks
    def main():
        while True:
            check_emails()
            time.sleep(60)  # Check every minute to see if it's time to run a check
    
    if __name__ == "__main__":
        main()



What Will Be Sent in the Email:
Only the Subject and ReceivedTime will be included in the table.
Rows will be ordered by ReceivedTime in ascending order.
Missing emails (those not found in the inbox) will be displayed with:
Subject: The missing email subject.
ReceivedTime: A message "No email found".
Rows where the Subject or ReceivedTime is missing will be highlighted in red.
Example Output in Email:
Assume you're expecting the following subjects:

Type 1 Expected Subjects: "Subject 1a", "Subject 1b", "Subject 1c"
Type 2 Expected Subjects: "Subject 2a", "Subject 2b"
Type 3 Expected Subjects: "Subject 3a", "Subject 3b", "Subject 3c"
After the check, let's say you found the following:

Found: "Subject 1a", "Subject 3b", "Subject 3c"
Missing: "Subject 1b", "Subject 1c", "Subject 3a", "Subject 2a", "Subject 2b"



<html>
    <body>
        <h2>Email Report</h2>
        <table border="1">
            <tr>
                <th>Subject</th>
                <th>ReceivedTime</th>
            </tr>
            <tr>
                <td>Subject 1a</td>
                <td>2025-01-14 09:35:00 AM</td>
            </tr>
            <tr>
                <td>Subject 3b</td>
                <td>2025-01-14 04:00:00 PM</td>
            </tr>
            <tr>
                <td>Subject 3c</td>
                <td>2025-01-14 04:10:00 PM</td>
            </tr>
            <tr style="background-color: red;">
                <td>Subject 1b</td>
                <td>No email found</td>
            </tr>
            <tr style="background-color: red;">
                <td>Subject 1c</td>
                <td>No email found</td>
            </tr>
            <tr style="background-color: red;">
                <td>Subject 3a</td>
                <td>No email found</td>
            </tr>
            <tr style="background-color: red;">
                <td>Subject 2a</td>
                <td>No email found</td>
            </tr>
            <tr style="background-color: red;">
                <td>Subject 2b</td>
                <td>No email found</td>
            </tr>
        </table>
    </body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.