Close
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.
Look at this SQLRPGLE code snippet:
exec sql set :myCount = regexp_count( :myEmail, '^(?:\w+\.?)*\w+@(?:\w+\.)*\w+$' ); If myCount = 1; // email is good else; // email is malformed endif;
Pretty simple huh!
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:
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):
// --------------------------------------------------------------------// Example SQL RPG program : VLD8EMAIL // Author : Nick Litten // ? CRTSQLRPGI ??OBJ(LITTENN/VLD8EMAIL) // SRCFILE(LITTENN/QSQLSRC) // SRCMBR(VLD8EMAIL) // OBJTYPE(*PGM) // 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); end-pi; dcl-pr email_is_valid IND; // this is our subprocedure - put this in a *SRVPGM to share it *n like(email); end-pr; if email_is_valid(email); display_window ('Email Address ' + %trim(email) + ' is valid'); else; display_window ('Yuk! Email Address ' + %trim(email) + ' is very naughty indeed. Bad Email! '); endif; *inlr = *on; return; // -------------------------------------------------------------------- // 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); end-pi; dcl-s myCount uns(10); // you can change this Regex string to anything you like!!! dcl-s myEmailValidationRegex varchar(100) inz('^(?:\w+\.?)*\w+@(?:\w+\.)*\w+$'); exec sql set :myCount = regexp_count(:myEmail, :myEmailValidationRegex); If myCount = 1; return *on; else; return *off; endif; end-proc; // -------------------------------------------------------------------- // 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); end-pi; 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; end-ds; 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) like(myapierror); end-pr; 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 ); end-proc;
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); end-pr; dcl-s email varchar(255); email = 'nick@nicklitten.com'; tst_email(email); email = 'nick@this-is_a@very$duff email'; tst_email(email); *inlr = *on;
and when I call my TEST program I see these two sceeens:
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, Alpha Nerd 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 in the words of the most interesting man in the world: Stay thirsty my friend.
What is IBM i Email and SPF?
So, I received a hacked email with an old password! Demanding payment with Bitcoin! #Blackmail
Funky IBM i Email Validation Program using SQL Regex
Use IBM i SQL to validate email addresses in Customer Master File
Email every spool file in an output queue – EMLOUTQ for IBM i
From AS400 DLS to IBM i IFS – Evolution of an Integrated File System
Send IBM i Email including SQL Table Data automatically
Working on a new signature for my emails .sig
Email all SPLF in an output queue – EMLOUTQ for ISERIES and AS400