Enviar correos electronicos en ABAP: CL_BCS, HTML y adjuntos

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

En ABAP, los correos electronicos se envian a traves de Business Communication Services (BCS). La clase CL_BCS proporciona una interfaz simple para crear, formatear y enviar correos electronicos desde sistemas SAP.

Componentes de BCS

ClaseDescripcion
CL_BCSClase principal para envio de correos
CL_DOCUMENT_BCSDocumento (cuerpo del correo + adjuntos)
CL_CAM_ADDRESS_BCSDireccion de correo externa
CL_SAPUSER_BCSUsuario SAP como destinatario

Requisitos

  • SAPconnect debe estar configurado (transaccion SCOT)
  • Autorizaciones para envio de correos
  • El servidor SMTP debe estar configurado

Ejemplos

1. Correo simple

DATA: lo_bcs TYPE REF TO cl_bcs,
lo_document TYPE REF TO cl_document_bcs,
lo_recipient TYPE REF TO if_recipient_bcs,
lv_text TYPE string.
TRY.
" Crear instancia BCS
lo_bcs = cl_bcs=>create_persistent( ).
" Crear documento (cuerpo del correo)
lv_text = 'Este es el texto del correo.'.
lo_document = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = CONV #( VALUE soli_tab( ( line = lv_text ) ) )
i_subject = 'Asunto de prueba'
).
" Establecer documento
lo_bcs->set_document( lo_document ).
" Establecer destinatario
lo_recipient = cl_cam_address_bcs=>create_internet_address(
i_address_string = '[email protected]'
).
lo_bcs->add_recipient( lo_recipient ).
" Enviar
lo_bcs->send( ).
COMMIT WORK.
WRITE: / 'Correo enviado exitosamente'.
CATCH cx_bcs INTO DATA(lx_bcs).
WRITE: / 'Error:', lx_bcs->get_text( ).
ENDTRY.

2. Correo con multiples lineas de texto

DATA: lt_text TYPE soli_tab.
" Crear varias lineas
lt_text = VALUE #(
( line = 'Estimado/a cliente,' )
( line = '' )
( line = 'Este es un correo de notificacion automatica.' )
( line = 'Su pedido ha sido procesado.' )
( line = '' )
( line = 'Saludos cordiales,' )
( line = 'Su equipo SAP' )
).
lo_document = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = lt_text
i_subject = 'Confirmacion de pedido'
).

3. Correo HTML

DATA: lt_html TYPE soli_tab.
lt_html = VALUE #(
( line = '<html>' )
( line = '<head><style>' )
( line = 'body { font-family: Arial; }' )
( line = '.header { color: #0066cc; font-size: 18px; }' )
( line = '.content { margin-top: 20px; }' )
( line = '</style></head>' )
( line = '<body>' )
( line = '<div class="header">Confirmacion de pedido</div>' )
( line = '<div class="content">' )
( line = '<p>Estimado/a cliente,</p>' )
( line = '<p>Su pedido <b>4711</b> ha sido procesado.</p>' )
( line = '<table border="1">' )
( line = '<tr><th>Posicion</th><th>Material</th><th>Cantidad</th></tr>' )
( line = '<tr><td>10</td><td>MAT-001</td><td>5</td></tr>' )
( line = '<tr><td>20</td><td>MAT-002</td><td>3</td></tr>' )
( line = '</table>' )
( line = '</div>' )
( line = '</body></html>' )
).
lo_document = cl_document_bcs=>create_document(
i_type = 'HTM' " HTML
i_text = lt_html
i_subject = 'Confirmacion de pedido #4711'
).

4. HTML dinamico desde tabla de datos

METHOD create_html_table.
DATA: lt_html TYPE soli_tab.
" Encabezado HTML
APPEND VALUE #( line = '<html><body>' ) TO lt_html.
APPEND VALUE #( line = '<h2>Informe de ventas</h2>' ) TO lt_html.
APPEND VALUE #( line = '<table border="1" cellpadding="5">' ) TO lt_html.
APPEND VALUE #( line = '<tr style="background:#eee">' ) TO lt_html.
APPEND VALUE #( line = '<th>Cliente</th><th>Cantidad</th><th>Ventas</th>' ) TO lt_html.
APPEND VALUE #( line = '</tr>' ) TO lt_html.
" Lineas de datos
LOOP AT it_sales INTO DATA(ls_sale).
APPEND VALUE #( line = '<tr>' ) TO lt_html.
APPEND VALUE #( line = |<td>{ ls_sale-customer }</td>| ) TO lt_html.
APPEND VALUE #( line = |<td>{ ls_sale-quantity }</td>| ) TO lt_html.
APPEND VALUE #( line = |<td>{ ls_sale-amount }</td>| ) TO lt_html.
APPEND VALUE #( line = '</tr>' ) TO lt_html.
ENDLOOP.
" Fin HTML
APPEND VALUE #( line = '</table></body></html>' ) TO lt_html.
rt_html = lt_html.
ENDMETHOD.

5. Correo con adjunto (PDF, Excel, etc.)

DATA: lo_document TYPE REF TO cl_document_bcs,
lt_content TYPE solix_tab,
lv_size TYPE i.
" Cargar datos de archivo (por ejemplo, de XSTRING)
lt_content = cl_document_bcs=>xstring_to_solix( iv_xstring ).
lv_size = xstrlen( iv_xstring ).
" Crear documento principal
lo_document = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = VALUE soli_tab( ( line = 'Vea el informe adjunto.' ) )
i_subject = 'Informe mensual'
).
" Agregar adjunto
lo_document->add_attachment(
i_attachment_type = 'PDF'
i_attachment_subject = 'Informe_2024.pdf'
i_attachment_size = lv_size
i_att_content_hex = lt_content
).
lo_bcs->set_document( lo_document ).

6. Adjuntar CSV

DATA: lt_csv TYPE soli_tab.
" Crear contenido CSV
lt_csv = VALUE #(
( line = 'ID;Nombre;Cantidad;Precio' )
( line = '1;Material A;10;100.00' )
( line = '2;Material B;5;250.00' )
( line = '3;Material C;20;75.50' )
).
" Agregar como adjunto
lo_document->add_attachment(
i_attachment_type = 'CSV'
i_attachment_subject = 'Datos_exportacion.csv'
i_att_content_text = lt_csv
).

7. Multiples destinatarios (TO, CC, BCC)

DATA: lo_recipient TYPE REF TO if_recipient_bcs.
" Destinatario principal (TO)
lo_recipient = cl_cam_address_bcs=>create_internet_address(
i_address_string = '[email protected]'
i_address_name = 'Sr. Principal'
).
lo_bcs->add_recipient(
i_recipient = lo_recipient
i_express = abap_true " Alta prioridad
).
" Copia (CC)
lo_recipient = cl_cam_address_bcs=>create_internet_address(
i_address_string = '[email protected]'
).
lo_bcs->add_recipient(
i_recipient = lo_recipient
i_copy = abap_true " CC
).
" Copia oculta (BCC)
lo_recipient = cl_cam_address_bcs=>create_internet_address(
i_address_string = '[email protected]'
).
lo_bcs->add_recipient(
i_recipient = lo_recipient
i_blind = abap_true " BCC
).

8. Enviar a usuario SAP

" Usuario SAP como destinatario
DATA(lo_sap_user) = cl_sapuser_bcs=>create( sy-uname ).
lo_bcs->add_recipient( lo_sap_user ).

9. Establecer remitente

" Remitente personalizado
DATA(lo_sender) = cl_cam_address_bcs=>create_internet_address(
i_address_string = '[email protected]'
i_address_name = 'Sistema SAP'
).
lo_bcs->set_sender( lo_sender ).

10. Multiples adjuntos

" Primer adjunto (PDF)
lo_document->add_attachment(
i_attachment_type = 'PDF'
i_attachment_subject = 'Informe.pdf'
i_attachment_size = lv_size_pdf
i_att_content_hex = lt_pdf_content
).
" Segundo adjunto (Excel)
lo_document->add_attachment(
i_attachment_type = 'XLS'
i_attachment_subject = 'Datos.xlsx'
i_attachment_size = lv_size_xls
i_att_content_hex = lt_excel_content
).
" Tercer adjunto (Imagen)
lo_document->add_attachment(
i_attachment_type = 'PNG'
i_attachment_subject = 'Logo.png'
i_attachment_size = lv_size_img
i_att_content_hex = lt_image_content
).

11. Clase completa para envio de correos

CLASS zcl_email_sender DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES: BEGIN OF ty_attachment,
filename TYPE string,
type TYPE char3,
content TYPE xstring,
END OF ty_attachment,
ty_attachments TYPE TABLE OF ty_attachment WITH EMPTY KEY.
METHODS:
send_email
IMPORTING
iv_to TYPE string
iv_cc TYPE string OPTIONAL
iv_subject TYPE string
iv_body TYPE string
iv_html TYPE abap_bool DEFAULT abap_false
it_attachments TYPE ty_attachments OPTIONAL
RAISING
cx_bcs.
ENDCLASS.
CLASS zcl_email_sender IMPLEMENTATION.
METHOD send_email.
DATA: lo_bcs TYPE REF TO cl_bcs,
lo_document TYPE REF TO cl_document_bcs,
lt_body TYPE soli_tab.
" Crear BCS
lo_bcs = cl_bcs=>create_persistent( ).
" Preparar cuerpo
" Dividir texto en lineas de 255 caracteres
DATA(lv_offset) = 0.
DATA(lv_len) = strlen( iv_body ).
WHILE lv_offset < lv_len.
DATA(lv_chunk) = substring( val = iv_body off = lv_offset len = nmin( val1 = 255 val2 = lv_len - lv_offset ) ).
APPEND VALUE #( line = lv_chunk ) TO lt_body.
lv_offset = lv_offset + 255.
ENDWHILE.
" Crear documento
lo_document = cl_document_bcs=>create_document(
i_type = COND #( WHEN iv_html = abap_true THEN 'HTM' ELSE 'RAW' )
i_text = lt_body
i_subject = CONV #( iv_subject )
).
" Agregar adjuntos
LOOP AT it_attachments INTO DATA(ls_attach).
DATA(lt_hex) = cl_document_bcs=>xstring_to_solix( ls_attach-content ).
lo_document->add_attachment(
i_attachment_type = ls_attach-type
i_attachment_subject = CONV #( ls_attach-filename )
i_attachment_size = xstrlen( ls_attach-content )
i_att_content_hex = lt_hex
).
ENDLOOP.
lo_bcs->set_document( lo_document ).
" Destinatario TO
lo_bcs->add_recipient(
cl_cam_address_bcs=>create_internet_address( iv_to )
).
" Destinatario CC
IF iv_cc IS NOT INITIAL.
lo_bcs->add_recipient(
i_recipient = cl_cam_address_bcs=>create_internet_address( iv_cc )
i_copy = abap_true
).
ENDIF.
" Enviar
lo_bcs->send( ).
COMMIT WORK.
ENDMETHOD.
ENDCLASS.

12. Uso de la clase de correo

DATA: lo_sender TYPE REF TO zcl_email_sender,
lt_attach TYPE zcl_email_sender=>ty_attachments.
CREATE OBJECT lo_sender.
" Correo simple
lo_sender->send_email(
iv_subject = 'Prueba'
iv_body = 'Este es un correo de prueba.'
).
" Correo HTML con adjunto
lt_attach = VALUE #(
( filename = 'Informe.pdf' type = 'PDF' content = lv_pdf_content )
).
lo_sender->send_email(
iv_subject = 'Informe mensual'
iv_body = '<html><body><h1>Informe</h1><p>Vea el adjunto.</p></body></html>'
iv_html = abap_true
it_attachments = lt_attach
).

13. Verificar estado del correo

DATA: lo_bcs TYPE REF TO cl_bcs,
lv_sent TYPE os_boolean,
lv_requested TYPE os_boolean.
lo_bcs = cl_bcs=>create_persistent( ).
" ... configurar correo ...
" Enviar inmediatamente (no en cola)
lo_bcs->set_send_immediately( abap_true ).
lv_sent = lo_bcs->send( i_with_error_screen = abap_true ).
IF lv_sent = abap_true.
WRITE: / 'Correo enviado exitosamente'.
ELSE.
WRITE: / 'Error al enviar'.
ENDIF.
COMMIT WORK.

Resumen

TareaMetodo/Clase
Crear correocl_bcs=>create_persistent( )
Texto/HTMLcl_document_bcs=>create_document( )
Agregar adjuntolo_document->add_attachment( )
Dest. externocl_cam_address_bcs=>create_internet_address( )
Usuario SAPcl_sapuser_bcs=>create( )
CC/BCCadd_recipient( i_copy/i_blind = abap_true )
Enviarlo_bcs->send( ) + COMMIT WORK

Notas importantes / Mejores practicas

  • COMMIT WORK es obligatorio despues de send( ) - sino el correo no se envia.
  • SAPconnect (SCOT) debe estar configurado correctamente.
  • Para HTML usar i_type = 'HTM' en create_document.
  • Los archivos adjuntos deben convertirse a SOLIX_TAB (binario).
  • Probar primero en sistemas de desarrollo (SCOT -> Probar).
  • Considerar los limites de tamano de correo del servidor SMTP.
  • En ABAP Cloud: usar la API de correo apropiada (CL_BCS no disponible).