Sending an email from z/OS

This started off as a question to me about TLS certificates and ended up with a Python solution.

The short version of this blog post is I could send an email to Gmail using Python – but could not use the IBM CSSMTP solution because it does not support authentication. I was also sent a link to Sending Email from z/OS using Java.

As far as I can tell, SMTP authentication does not use client certificates. If you want to use userid and password, make sure the session is encrypted using TLS.

What types of email are there?

Through JES spool

On my system with id S0W1, I can use TSO XMIT S0W1.IBMUSER and send an email.

The recipient (IBMUSER) can use TSO receive to read the email.

You can use XMIT OVERTHER.MYID to send the email over NJE to other system, such as z/OS, z/VM and z/VSE. You say (on z/OS) xmit node.userid da(‘…’). or xmit node.userid . The JES2 configuration has an IP address and port to send it to a remote spool.

JES2 destinations

You can configure destinations on JES2, and have program (“a writer”) process the node name (destination) data.

You can display the defined destinations using the JES2 command

$DDESTID

Example JCL to write to a destination,

//COPY EXEC PGM=IEBGENER 
//SYSPRINT DD SYSOUT=* 
//SYSIN DD DUMMY 
//SYSUT2 DD SYSOUT=(A,MYDEST),SPIN=UNALLOC 
//SYSUT1 DD * 
line1
/*
// 

This writes the data from SYSUT1 to SYOUT2 which goes to nodename MYDEST.

You configure CSSMP and specify ExtWrtName MYDEST, for CSSMTP to read from.

SMTP

There is Simple Mail Transport Protocol. A stream of data is provided such as

MAIL FROM:<ME@MYSYSTEM.COM> 
RCPT TO:<MYBOSS@MYSYSTEM.COMU> 
RCPT TO:<YOU@yoursystem.com> 
DATA 
Blah blah blah. 
QUIT 

which is sent to the mail server over TCPIP (usually port 25 or 587).

SMTP is a popular protocol. It can support encrypted session encryption. The protocol can support different levels of authorisation.

z/OS provides CSSMTP which reads from the spool and sends the data over TCPIP to a server. However CSSMTP does not seems to support the passing of authentication information to the server – and as most mail servers want you to authenticate before sending emails – CSSMTP cannot be used for these. I know this from the documentation because the AUTH command is not listed in the list of supported SMTP commands, and AUTH does not work!

Using Python to send an email.

I used Python to send an email to my Gmail account. The script I used is

#!/usr/bin/python 
import smtplib 
import ssl 
import sys 
from email.mime.text import MIMEText 
host = "173.194.76.108" 
sender = 'colinpaicetest@gmail.com' 
receivers = ['colinpaicemq@gmail.com','colinpaicetest@gmail.com'] 
msg = MIMEText('This is test mail2') 
msg['Subject'] = 'Test mail3' 
msg['From'] = 'colinpaice3@gmail.com' 
msg['To'] ='colinpaicemq@gmail.com , colinpaicetest@gmail.com' 
with smtplib.SMTP(host , 587) as server: 
      # if you need to validate the certificate sent to client.. you need a context
      context=ssl.create_default_context(
                 purpose=ssl.Purpose.CLIENT_AUTH,cafile="pem.pem") 
      server.starttls(context=context) 
      # server.starttls() # for servers that do not send a certificate 
      print(server.esmtp_features) # print info about the connection such as auth types
      server.login('colinpaice3@gmail.com', 'abcpasswordxyz') 
      server.sendmail(sender, receivers, msg.as_string()) 
      print("Successfully sent email") 
  • context=ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH,cafile=”pem.pem”) is used to set up the CA cert for verifying any certificate sent from the server. GMAIL does not send a certificate, so the CA is not needed, and you can use server.starttls()
  • server.starttls(context=context) creates the TLS session. This is handled by PAGENT.
  • server.login(‘colinpaice3@gmail.com’, ‘ZYC123….’) does the authentication
  • server.sendmail(sender, receivers, msg.as_string()) sends the message.

The id in the sender must match the id in the login.

This does not use PAGENT or AT-TLS.

In the TLS handshake 57 cipher specs were sent to the server, and cipher spec TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xC02B) was used.

Setting up CSSMTP

Basic configuration

Even though I could not use CSSMTP because I could not authenticate, I learned a lot on my doomed journey.

In the CSSMTP configuration I had

ExtWrtName    MYDEST             # the external writer name 
TargetServer 
{ 
   TargetIp aaa.bbb.ccc.ddd      # This IP address 
  # TargetName  
   ConnectPort   25              # port to connect to target server 
   Secure        Yes             # Transport Layer Security (TLS) 
} 
...

Each CSSMTP instance reads from one nodeName and sends to one server. If you want to support more nodeNames you need more CSSMTP instances.

Certificates

As part of the TLS handshake, some servers will send down a certificate (to authenticate the server).

If your TLS provider, such as AT-TLS, uses keyrings, you need to import certificate into RACF, and connect the CA certificate to the keyring. Your keyring needs the CA for this certificate. You can get the servers certificate from the network flow, or from an openssl command.

If you are not using keyrings, for example Python uses openssl, you need the certificate in a file in Unix Services.