Python: Send SSL Cert Expirations to Teams

If your organization uses SSL certificates for servers and websites, manually tracking their expiration dates can be time-consuming. This Python script automates this process by:

  1. Reading a list of URLs from a text file.
  2. Validating each SSL certificate’s issuer and expiration date.
  3. Sending alerts to a specified Microsoft Teams channel for certificates nearing expiration (within a customizable timeframe).

Note: Most registrars won’t renew SSL certs more than 30 days before they expire.

Need help with the Microsoft Teams webhook setup?  I’ve included a brief guide below to get you started.

 

Create Microsoft Teams Webhook

If you haven’t already, create a Teams channel to host your domain alerts.  Click the there *** (dots) on the name of the channel and choose Manage channel.

 

 

If not already expanded, expand the area under Connectors.  Choose Edit. 

Search for Incoming Webhook if the connector isnt already showing in your options.  Click Configure.

 

 

 

Create your webhook name, and upload an image (optional) for your webhook and click Create.  

Last thing you need to do is copy the Webhook URL.  You will need this for the Python script.  Click the X button to close the pop-up.

Looking to do this via PowerShell Instead? Check out this page

Python Script

Now that you have your Teams Webhook URL, it’s time to setup your alert script.   Below is the script you can copy.  Make sure you update the .txt file path and Webhook URL with your own information. 

				
					import socket
import ssl
import datetime
import requests

# Define your path to the URL file
urls_file = "/Users/daveherrell/Desktop/urls.txt"

# Define the Teams Webhook URL you created
teams_webhook_url = "YOURTEAMSWEBHOOKURLHERE"

# Set the number of days to check for certificate expiration
warning_days = 90

# Function to fetch SSL certificate information
def get_ssl_certificate_info(url):
    try:
        hostname = url.replace("https://", "").replace("http://", "").split("/")[0]
        context = ssl.create_default_context()
        
        with socket.create_connection((hostname, 443)) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                cert = ssock.getpeercert()
        
        not_after = datetime.datetime.strptime(cert['notAfter'], "%b %d %H:%M:%S %Y %Z")
        issuer = dict(x[0] for x in cert['issuer'])['organizationName']
        registrar = cert.get('subjectAltName', [(None, hostname)])[0][1]
        
        return {
            "url": url,
            "issuer": issuer,
            "not_after": not_after,
            "registrar": registrar,
            "is_valid": True
        }
    except Exception as e:
        print(f"Failed to fetch certificate for {url}: {e}")
        return None

# Function to send a notification to Teams
def send_teams_notification(message):
    payload = {
        "@type": "MessageCard",
        "@context": "http://schema.org/extensions",
        "summary": "SSL Certificate Expiry Alert",
        "themeColor": "FF0000",
        "title": "SSL Certificate Expiry Alert",
        "text": message
    }
    
    response = requests.post(teams_webhook_url, json=payload)
    if response.status_code != 200:
        print(f"Failed to send Teams message: {response.status_code}, {response.text}")

# Read URLs from file and process each
try:
    with open(urls_file, "r") as f:
        urls = [line.strip() for line in f if line.strip()]

    for url in urls:
        cert_info = get_ssl_certificate_info(url)
        if cert_info and cert_info["is_valid"]:
            days_to_expire = (cert_info["not_after"] - datetime.datetime.utcnow()).days
            if days_to_expire <= warning_days:
                message = (
                    f"SSL Certificate for {cert_info['url']} issued by {cert_info['issuer']} "
                    f"(Registrar: {cert_info['registrar']}) will expire in {days_to_expire} days "
                    f"on {cert_info['not_after'].strftime('%Y-%m-%d')}."
                )
                send_teams_notification(message)
                print(message)
        else:
            print(f"Invalid certificate for {url} or unable to retrieve certificate.")
except FileNotFoundError:
    print(f"URLs file not found at {urls_file}")
				
			

A couple items to note:

  • You can change the date range on line 13 with whatever you wish.  Just make sure it’s in days.  For instance you can set it for 30 days instead of 90 days.
  • Within your TXT file, you can list up to five hundred URLs before this breaks.  However, make sure the file only contains one domain per line!
  • You can easily set this script to run via Scheduled task on Windows server or with a cron job on any Linux setup.
  • Even if the url in the txt file is no longer available, the script will still run. 
  • Make sure the request module is installed, along with any others you may need for import. 

The Results

Finally you should be able to run your Python script and receive your alerts.  You should get a similar Teams alert:

 

And there you have it.  Simple SSL Expiration Alerts to your Microsoft Teams Channel. 

Hope you find this helpful!