Email notifications for Color 64 BBS 8.1 Sysop

The following steps, scripts and code modifications will create an email notification to a desired email address for BBS events. I have also added a “heartbeat” routine that will generate an email every six hours to me saying the BBS is alive.

With my computer setup and operating this mod, it adds about 10 seconds to the logoff → BBS Ready for call process.

Requirements: linux box with python3 installed, to include smtplib
Window gurus, feel free to post reply on how to make this compatible with Windows!

Upfront note: Color 64 cannot send encrypted traffic, so username and password are exposed in transmissions. I recommend using this on internal networked computer only that does not have the assigned port (in my example below, 8502) exposed to outside world. Otherwise, you open up a potential email resource for those hackers out there!

  1. Create python script for email server - for this example, we will name it bbsnotify.py
import socket
import smtplib

# Configuration
HOST = "0.0.0.0"  # Listen on all interfaces
PORT = 8502        # Telnet port
USERNAME = "*enter your username here*"  # Example username
PASSWORD = "enter your password here"  # Example password
SMTP_SERVER = "enter your SMTP server"
SMTP_PORT = 587
EMAIL_FROM = "enter your email address here"
EMAIL_TO = "enter desired recipient email here"
EMAIL_SUBJECT = "BBS Event Notification"
EMAIL_PASSWORD = "enter your SMTP password here"  # Use environment variables in production
TIMEOUT_SECONDS = 10  # Timeout for user input

def send_email(event_message):
    """Send an email notification with multi-line event message."""
    try:
        print("Connecting to SMTP server...")  # Debug log

        # Create an email message with headers
        msg = EmailMessage()
        msg["Subject"] = EMAIL_SUBJECT
        msg["From"] = EMAIL_FROM
        msg["To"] = EMAIL_TO
        msg["Reply-To"] = "mike.newkirk@gmail.com"  # Set custom Reply-To
        msg.set_content(event_message)  # Allow multi-line content

        # Connect to SMTP
        server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT, timeout=10)
        server.starttls()
        server.login(EMAIL_FROM, EMAIL_PASSWORD)
        server.send_message(msg)  # Send the email using the email.message object
        server.quit()

        print("Email successfully sent!")  # Debug log
        return True
    except Exception as e:
        print(f"Email error: {e}")
        return str(e)  # Return error message

def receive_multiline(client_socket):
    """Receive multiple lines of input until 'END' is entered or timeout occurs."""
    client_socket.send(b"Enter Event (type 'END' on a new line to finish):\r\n")
    lines = []
    client_socket.settimeout(TIMEOUT_SECONDS)  # Set timeout

    try:
        while True:
            line = receive_line(client_socket)
            if line is None:
                break  # Timeout or client disconnected
            if line.strip().upper() == "END":
                return "\n".join(lines)  # Preserve newlines in email body
            lines.append(line)
    except socket.timeout:
        client_socket.send(b"\r\nTimeout reached. Connection closing.\r\n")
        print("Timeout reached. Closing connection.")
        return None  # Indicate timeout occurred

    return "\n".join(lines)

def receive_line(client_socket):
    """Receive a full line from the client, handling Telnet input properly."""
    data = b""
    while True:
        try:
            chunk = client_socket.recv(1)
            if not chunk:
                return None  # Client disconnected
            if chunk in [b"\n", b"\r"]:  # End of input line
                break
            data += chunk
        except socket.timeout:
            return None  # Timeout reached
    return data.decode(errors='ignore').strip()

def handle_client(client_socket):
    """Handle the Telnet connection."""
    try:
        client_socket.send(b"Username: ")
        username = receive_line(client_socket)
        print(f"Received username: {username}")  # Debug log

        client_socket.send(b"Password: ")
        password = receive_line(client_socket)
        print(f"Received password: {password}")  # Debug log

        if username == USERNAME and password == PASSWORD:
            event_message = receive_multiline(client_socket)  # Allow multi-line input
            if event_message:
                print(f"Received event:\n{event_message}")  # Debug log
                result = send_email(event_message)
                if result is True:
                    client_socket.send(b"Event notification sent.\r\n")
                else:
                    error_msg = f"Failed to send notification: {result}\r\n"
                    client_socket.send(error_msg.encode())  # Send SMTP error message
            else:
                client_socket.send(b"No event entered. Closing connection.\r\n")
        else:
            client_socket.send(b"Authentication failed.\r\n")

    except Exception as e:
        print(f"Error handling client: {e}")

    finally:
        print("Closing connection")  # Debug log
        client_socket.close()

def start_server():
    """Start the Telnet server."""
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind((HOST, PORT))
    server.listen(5)
    print(f"Server listening on port {PORT}...")

    while True:
        try:
            client_socket, addr = server.accept()
            print(f"Connection from {addr}")
            handle_client(client_socket)
        except KeyboardInterrupt:
            print("\nServer shutting down.")
            server.close()
            break

if __name__ == "__main__":
    start_server()

#Instructions:
#Modify the USERNAME, PASSWORD, SMTP_SERVER, and email details.
#Start the script: python3 bbsnotify.py
#Connect via Telnet: telnet <your_server_ip> 8502
#Enter the username, password, and event. 
#Ensure "end" is last transmission alone on a line.
#The script will send the event via email.
  1. Determine the IP of your linux computer running the script for reference
  2. Run the script at your linux computer
  3. At the Commodore 64, edit and save √bbs.init with the following modifications:

35700 rem email notification
35702 .21:!12.:'“+++”:gosub35725
35705 ‘“ATDT your-internal-ip-address-here:8502”:gosub35725:’“your-username”:gosub35725
35706 '“your-password”:gosub35725:gosub1110:'da$+" “+t$+” "+cr$+em$+cr$+“end”+cr$:return
35725 forxx=1to500:nextxx:return

The loop at 35725 will give enough time for responses from the linux email script, though it can probably be shortened some, but this worked fine for my system.

EM$ is obviously what is being used to record specific events. This must also be cleared out at some point after each transmission. Below are my placements and use for EM$:

  • Clearing of EM string:
    Line 12014 where √wfc is being loaded, add EM$=“” here

12014 !17,.!18,.:!16,1:em$=“”:f$=“√wfc”:gosub205

My selected events:

  • Modify line 12185 to reflect a logon

12185 ifpw$=i$then#“Loading parameters…”:em$=“logon ok”:goto12300

  • Add line 12486

12486 em$=em$+cr$+@21(na$)+" entered system"

  • modify line 18200 for new user

18200 nu=nu+1:em$=em$+cr$+"new user! "+@21(na$)

  • Modify line 12650 to report a system shutdown

12650 em$=em$+cr$+“system shutdown ordered!”:gosub35700:.05:goto9999

  • Finally, add a post-logoff event to run the routine:

19046 gosub35700

What it does
The system will track events in EM$ wherever you put it. Just remember to do “EM$=EM$+CR$+”" wherever you want something recorded. Because we are using PETSCII - something the linux server is not - be sure not to use capital letters; keep everything lower case. If using a username, convert username using @21 function: @21(na$)

To add heartbeat “BBS is alive!” routine:

  • 1st, add these following lines to √bbs.init

12051 ifhb=1then12054
12052 ifleft$(t$,4)="6:00"orleft$(t$,5)="12:00"thenhb=1:em$=“heart”:gosub35700
12054 ifleft$(t$,4)="6:02"orleft$(t$,5)="12:02"thenhb=0

  • Next, in the same file, modify your routine at 35700 by adding this line (35701):

35701 ifem$="heart"thenem$=“heartbeat!”+cr$+“my bbs is alive!”

You can place other events in √bbs.msgs and √bbs.xfers in the same manner using em$. The handling routine for email only needs to be in √bbs.init. I have alerts set for user uploads and sysop feedback submitted.

With the script running, the commodore at post-logoff will telnet to your linux box and enter the details for the email to be sent; after which, it will disconnect and clear EM$, then go back to the wait-for-caller screen. With a little tweaking of the email script, this can be expanded to send notifications to users! As a Bonus for your efforts, my Game Mods I have on this website already store events for this feature, so you will see what games are being utilized and by whom.

This is the observation at the linux box:

I use Brevo for my SMTP service - they are great. The only thing I noticed is emails were going straight to junk folder, so I applied a rule in my outlook to push those emails into a specific folder and that resolved the issue.

1 Like