ABAP 程序中使用正则表达式验证邮箱格式是否正确

举报
雨绸缪 发表于 2023/07/24 14:50:15 2023/07/24
【摘要】 问题来源在开发过程中,经常会遇到一些数据校验的问题,比如我们必须从屏幕字段、Web Dynpro 输入字段或上传文件的文本中验证电子邮件地址。验证可确保您具有有效的电子邮件格式以进行进一步处理,例如发送通知或将其存储在数据库中。这次在实际业务中,用户比较看重邮件的正确性,如果是 SAP 的数据元素 AD_SMTPADR 就是带标准的校验功能的。如果我们输入不带 @ 符号的邮箱,就会在标准错...

问题来源

在开发过程中,经常会遇到一些数据校验的问题,比如我们必须从屏幕字段、Web Dynpro 输入字段或上传文件的文本中验证电子邮件地址。验证可确保您具有有效的电子邮件格式以进行进一步处理,例如发送通知或将其存储在数据库中。

这次在实际业务中,用户比较看重邮件的正确性,如果是 SAP 的数据元素 AD_SMTPADR 就是带标准的校验功能的。

image.png

如果我们输入不带 @ 符号的邮箱,就会在标准错误中得到如下的提示:

消息号 XS138:电子邮箱地址 XXXsam.com 无效

image.png

通过 DEBUG 可以看到这段程序:

IF ADDRESS_UNSTRUCT-ADDRESS NP '*@*' AND COMPLETE_ADDRESS = SX_TRUE.  
    MESSAGE E138 WITH ADDRESS_UNSTRUCT-ADDRESS ADDRESS_UNSTRUCT-TYPE  
                      TEXT-028 TEXT-039  
    RAISING ERROR_ADDRESS.  
ENDIF.

解读:从上面的代码可以看出有一个条件是查看 ADDRESS_UNSTRUCT-ADDRESS NP '*@*',它检查 ADDRESS_UNSTRUCT-ADDRESS 这个邮箱变量的值是否包含字符串 @。 如果包含就报出 E138 这个错误。

这段校验会有缺陷,当我们输入一个不带域名的邮箱时,不会得到系统的错误:

image.png

正则表达式

关于电子邮箱的正则表达式有很多,具体可以看一下这个网站提供了一些常见的正则库:RegExLib

这里使用一种常见的电子邮箱的正则表达式:\w+(\.\w+)*@(\w+\.)+(\w{2,4})

  • \w 表示匹配任意字母、数字、下划线
  • + 表示匹配前面的元素至少出现一次
  • * 表示匹配前面的元素任意次

接下来解释一下这个正则模式:

  • \w+(\.\w+): @ 前面的第一部分将接受任何字母、数字字符或带或不带 (.) 点的字符。这部分\w+ 匹配多个字母或数字。 (\.\w+) 验证是否有一个点,且 . 后面必须跟一个字符。
  • (\w+\.)@ 后面的部分允许灵活地使用任何名称(后面带有 (.) 点)。这一部分 (\w+\.) 确保结束部分之前至少有一个域。如果有多个,它将检查域的每个部分后面的 (.) 点。
  • (\w{2,4}):最后一部分确保电子邮件在最后一个点之后至少有 2 个字符,最多 4 个字符。

此外,你可以在 regerxr.com 中找到每种模式的解释

问题解决

SAP 提供了一个非常有用的API,让您可以使用正则表达式验证电子邮件地址。使用 ABAP RegEx 实用程序类 CL_ABAP_REGEXCL_ABAP_MATCHER 验证电子邮件。

验证电子邮件的步骤如下:

  • 首先,编写一个与电子邮件地址匹配的正则表达式。
  • 然后,创建一个类的实例 cl_abap_regex ,该实例具有名为 regex 对象的电子邮件地址模式。
  • 最后,从上面的 regex 对象创建一个 matcher 对象,它是 class 的实例 cl_abap_matcher ,并调用 匹配对象的 match() 方法。如果方法的返回值 match() 不为空,则电子邮件地址有效。否则无效。
REPORT  zvalidateemail.

DATA: go_regex   TYPE REF TO cl_abap_regex,
      go_matcher TYPE REF TO cl_abap_matcher,
      go_match   TYPE c LENGTH 1,
      gv_msg     TYPE string.

PARAMETERS: p_email TYPE ad_smtpadr.

START-OF-SELECTION.

  CREATE OBJECT go_regex
    EXPORTING
      pattern     = '\w+(\.\w+)*@(\w+\.)+(\w{2,4})'
      ignore_case = abap_true.

  go_matcher = go_regex->create_matcher( text = p_email ).

  IF go_matcher->match( ) IS INITIAL.
    gv_msg = 'Email address is invalid'.
  ELSE.
    gv_msg = 'Email address is valid'.
  ENDIF.

  MESSAGE gv_msg TYPE 'I'.

类实现

CLASS lcl_mail DEFINITION.
  PUBLIC SECTION.
    METHODS validate_email_id
      IMPORTING
        iv_email TYPE ad_smtpadr
      RETURNING
        VALUE(RESULT) TYPE flag .
ENDCLASS.                    "lcl_mail DEFINITION
*
START-OF-SELECTION.
  DATA: lo_mail TYPE REF TO lcl_mail.
  CREATE OBJECT lo_mail.
  IF lo_mail->validate_email_id( 'szdfd@' ) IS INITIAL.
    WRITE: 'Invalid Email'.
  ELSE.
    WRITE: 'Valid'.
  ENDIF.
*
CLASS lcl_mail IMPLEMENTATION.
  METHOD validate_email_id.
 
* Local Data
    DATA:  REGEX   TYPE REF TO cl_abap_regex,       " Regex Object
           matcher TYPE REF TO cl_abap_matcher,     " Matcher Object
           MATCH   TYPE c LENGTH 1,                 " Match ?
           mail_to_check(100).                      " Email ID to check
 
    mail_to_check = iv_email.
 
    RESULT = abap_true.  "Email is valid
 
* Instntiate Regex
    CREATE OBJECT REGEX
      EXPORTING
        pattern     = 'w+(.w+)*@(w+.)+(w{2,4})'
        ignore_case = abap_true.
 
* Create the Matcher
    matcher = regex->create_matcher( text = mail_to_check ).
 
* Match not found, invalid
    IF matcher->MATCH( ) IS INITIAL.
      RESULT = abap_false.  "Email not valid
      EXIT.
    ENDIF.
 
  ENDMETHOD.                    "validate_email_id
ENDCLASS.                    "lcl_mail IMPLEMENTATION

官方实现

程序通过将输入的电子邮件地址与正则表达式进行比较,检查其形式上的正确性。

  • 第一个正则表达式检查不含特殊字符的标准电子邮件地址,而第二个正则表达式则根据 RFC 822 执行更宽松的语法检查。
  • 即使是使用相对简单的正则表达式作为示例的第二种检查,也并非总是与 RFC 822 规定的所有电子邮件地址兼容。
  • DEMO_VALIDATE_RFC_822_ADDRESS 程序使用的正则表达式来自互联网,旨在识别 RFC 822 允许的所有电子邮件地址。这里的正则表达式最初是为 Perl 编写的,有 6000 多个字符。因此,该程序是如何在 ABAP 中不使用正则表达式的一个示例。
REPORT demo_matches.  
  
CLASS demo DEFINITION.  
  PUBLIC SECTION.  
    CLASS-METHODS main.  
ENDCLASS.  
  
CLASS demo IMPLEMENTATION.  
  METHOD main.  
    DATA email TYPE string VALUE `abc.def@ghi.jkl`.  
    cl_demo_input=>request( CHANGING field = email ).  
    IF matches( val   = email  
                regex = `\w+(\.\w+)*@(\w+\.)+(([a-z]|[A-Z]){2,4})` )  
                ##REGEX_POSIX.  
      cl_demo_output=>display( 'Format OK' ).  
    ELSEIF matches(  
             val  = email  
             pcre = `[[:alnum:],!#\$%&'\*\+/=\?\^_``\{\|}~-]+`      &  
                    `(\.[[:alnum:],!#\$%&'\*\+/=\?\^_``\{\|}~-]+)*` &  
                    `@[[:alnum:]-]+(\.[[:alnum:]-]+)*`              &  
                    `\.([[:alpha:]]{2,})` ).  
      cl_demo_output=>display( 'Syntax OK but unusual' ).  
    ELSE.  
      cl_demo_output=>display( 'Wrong format!' ).  
    ENDIF.  
  ENDMETHOD.  
ENDCLASS.  
  
START-OF-SELECTION.  
  demo=>main( ).
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。