Simple email validation SQL RPG ILE program 

 June 13, 2018

By  NickLitten

There are lots of code snippets, example programs and long waffling discussions in internet land filled with pointy headed AS400, iSeries and IBM i programmer chaps (and chappettes) arguing about the best way to “validate an email address in RPG”. I know because I’ve read nearly all of them, as well as tried all the techniques. But yesterday I stumbled across a really simple variation of an established technique.

Using Regex to validate an email

Look at this SQLRPGLE code snippet:

exec sql
    set :myCount = regexp_count( :myEmail, '^(?:\w+\.?)*\w+@(?:\w+\.)*\w+$' );

If myCount = 1;
  // email is good
  // email is malformed

Pretty simple huh!

So , what are we doing with this regular expression?

The regular expression ‘^(?:\w+\.?)*\w+@(?:\w+\.)*\w+$‘ is saying – check this input string meets the standard of something before an @ sign followed by something dot something:

Simple email validation SQL RPG ILE program 1

The internet is filled with alternate regular expressions to make the email validation logic as complex as you wish.

For my purposes this simple logic is exactly what I need.

So, let’s plumb this into a an example RPG program, wrapped in a tidy sub-procedure, with a sprinkling of comments, my favorite QUILNGTX *API for display screen messages without coding any DSPF and using variable length characters –  just for fun (Yes, I know, I need to get out more):

// --------------------------------------------------------------------
RPG Code Snippet// Example SQL RPG program : VLD8EMAIL
// Author : Nick Litten
// History:
// 2018-06-12 NJL Created
// --------------------------------------------------------------------
// This program accepts an input parameter of 'email address'.
// We validate it using a regular expression in SQL and
// display a message in a window telling you if the email
// address is good or bad. nice or naughty.
// Simple but Saucy.
// --------------------------------------------------------------------

ctl-opt dftactgrp(*no) option(*nodebugio:*srcstmt) ;

dcl-pi *n; // this is our program input a 255 long variable email address
  email varchar(255);

dcl-pr email_is_valid IND; // this is our subprocedure - put this in a *SRVPGM to share it
  *n like(email);

if email_is_valid(email);
  display_window ('Email Address ' + %trim(email) + ' is valid');
  display_window ('Yuk! Email Address ' + %trim(email) +
  ' is very naughty indeed. Bad Email! ');

*inlr = *on;

// --------------------------------------------------------------------
// PROCEDURE: email_is_valid
// --------------------------------------------------------------------
// Accept an input field (the email address) and validate it using
// a regular expression to perform basic email address syntax checks.
// REGEXP_COUNT Returns a returns a count of the number of times
// that a regular expression pattern is matched in a string
// The leading ^ and trailing $ match the beginning and the ending of
// the input string, respectively. That is, the entire input string
// shall match with this regexe, instead of a part of the input string.
// \w+ matches 1 or more word characters (a-z, A-Z, 0-9 and underscore).
// [.-] matches character . or -. We need to use . to represent . as . has
// special meaning in regexe. The \ is known as the escape code, which
// restore the original literal meaning of the following character.
// [.-]? matches 0 or 1 occurrence of [.-].
// ([.-]?\w+)* matches 0 or more occurrences of [.-]?\w+.
// The sub-expression \w+([.-]?\w+)* is used to match the username in
// the email, before the @ sign. It begins with at least one word
// character (a-z, A-Z, 0-9 and underscore), followed by more word
// characters or . or -. However, a . or - must follow by a word
// character (a-z, A-Z, 0-9 and underscore). That is, the string cannot
// contain "..", "--", ".-" or "-.". Example of valid string are "a.1-2-3".
// The @ matches itself.
// The sub-expression .\w{2,3} matches a . followed by two or three word
// characters, e.g., ".com", ".edu", ".us", ".uk", ".co".
// (.\w{2,3})+ specifies that the above sub-expression shall occur one or
// more times, e.g., ".com", ".co.uk", ".edu.sg" etc.
// --------------------------------------------------------------------

dcl-proc email_is_valid;
dcl-pi *n IND;
  myEmail like(email);
dcl-s myCount uns(10);

// you can change this Regex string to anything you like!!!
dcl-s myEmailValidationRegex varchar(100)

exec sql
  set :myCount = regexp_count(:myEmail, :myEmailValidationRegex);

If myCount = 1;
  return *on;
  return *off;

// --------------------------------------------------------------------
// PROCEDURE: display_window
// --------------------------------------------------------------------
// Use IBM i *API 'QUILNGTX' to dynamicalluy display messages in a
// window format rather than on the error message line
// --------------------------------------------------------------------

dcl-proc display_window export;
dcl-pi display_window;
  p_Text varchar(8192) const;
  p_MsgId char(7) Options(*nopass: *omit);
  p_MsgFile char(21) Options(*nopass: *omit);
dcl-ds myApiError inz qualified;
  Bytes int(10) inz(%size(myApiError));
  BytesAvailable int(10) inz;
  ErrorID char(7) inz;
  Reserved char(1) inz(x'00');
  MessageData char(128) inz;
dcl-pr QUILNGTX extpgm('QUILNGTX');
  *n char(8192) const;
  *n int(10) const;
  *n char(7) const;
  *n char(21) const;
  *n options(*omit: *varsize)
dcl-s myMsgId like(p_MsgId);
dcl-s myMsgFile like(p_MsgFile);
If %Parms = 1;
  myMsgId = 'CPF9999';
  myMsgFile = 'QCPFMSG';
Elseif %Parms = 2;
  myMsgId = p_MsgId;
  myMsgFile = 'QCPFMSG';
Elseif %Parms = 3;
  myMsgId = p_MsgId;
  myMsgFile = p_MsgFile;
Endif ;
QUILNGTX ( p_Text :
  %Len(p_Text) :
  myMsgId :
  myMsgFile :
  myApiError );

I hope that helps someone out?

Testing is easy – I just knocked together a little calling program, because calling variable length input parameters from an IBM i command line is painful:

dcl-pr tst_email extpgm('VLD8EMAIL'); 
*n varchar(255); 

dcl-s email varchar(255); 

email = 'nick@nicklitten.com'; 

email = 'nick@this-is_a@very$duff email'; 

*inlr = *on;

and when I call my TEST program I see these two sceeens:

Simple email validation SQL RPG ILE program 2

Simple email validation SQL RPG ILE program 3

PS: to test your regular expressions check out http://emailregex.com/regex-visual-tester/ it’s excellent!


IBM i Software Developer, Digital Dad, AS400 Anarchist, RPG Modernizer, Shameless Trekkie, Belligerent Nerd, Englishman Abroad and Passionate Eater of Cheese and Biscuits. Nick Litten Dot Com is a mixture of blog posts that can be sometimes serious, frequently playful and probably down-right pointless all in the space of a day. Enjoy your stay, feel free to comment and remember: If at first you don't succeed then skydiving probably isn't a hobby you should look into.

Nick Litten

related posts:

  • Nice work documenting and commenting, as well as including a usable subprocedure and test. Do you know whether IBM’s SNDSMTPEMM supports recipient email addresses with the “.bz” domain? The command throws a TCP530F Email Address Invalid whenever I try to use it with “.bz” domains.

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
    __CONFIG_colors_palette__{"active_palette":0,"config":{"colors":{"cff50":{"name":"Main Accent","parent":-1},"a344d":{"name":"Accent Transparent","parent":"cff50"}},"gradients":[]},"palettes":[{"name":"Default","value":{"colors":{"cff50":{"val":"var(--tcb-skin-color-0)"},"a344d":{"val":"rgba(46, 138, 229, 0.85)","hsl_parent_dependency":{"h":210,"l":0.54,"s":0.78}}},"gradients":[]},"original":{"colors":{"cff50":{"val":"rgb(0, 178, 255)","hsl":{"h":198,"s":1,"l":0.5}},"a344d":{"val":"rgba(0, 178, 255, 0.85)","hsl_parent_dependency":{"h":198,"s":1,"l":0.5}}},"gradients":[]}}]}__CONFIG_colors_palette__

    Get In Touch

    I’m always looking for awesome input, feedback and critique!