반응형
검증 전
Function Module: ZFI_GROUPWARE_SEND_MAIL
FUNCTION ZFI_GROUPWARE_SEND_MAIL.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(I_MAIL_API_URL) TYPE STRING
*" VALUE(I_EMP_ID) TYPE STRING " 발신자 사번
*" VALUE(I_SUBJECT) TYPE STRING " 메일 제목
*" VALUE(I_BODYTEXT) TYPE STRING " 메일 본문
*" VALUE(I_CERT_KEY) TYPE STRING DEFAULT 'ekdphandy'
*" TABLES
*" T_RECIPIENTS STRUCTURE ZSTFI_MAIL_RECIPIENT " 수신자 목록
*" T_ATTACHMENTS STRUCTURE ZSTFI_MAIL_ATTACH OPTIONAL " 첨부파일
*" EXPORTING
*" VALUE(E_SUCCESS) TYPE ABAP_BOOL
*" VALUE(E_MESSAGE) TYPE STRING
*" VALUE(E_RESPONSE) TYPE STRING
*" EXCEPTIONS
*" HTTP_COMMUNICATION_FAILURE
*" HTTP_INVALID_STATE
*"----------------------------------------------------------------------
*& PROGRAM ID : ZFI_GROUPWARE_SEND_MAIL &*
*& Title : [FI] 그룹웨어 메일 발송 API 연동 &*
*& Created By : [Your Name] &*
*& Created On : 2025.10.31 &*
*& Description : 그룹웨어 API를 통한 메일 발송 &*
*& Reference : GroupMailSender.java &*
*----------------------------------------------------------------------*
DATA: lo_http_client TYPE REF TO if_http_client,
lv_url TYPE string,
lv_json TYPE string,
lv_response TYPE string,
lv_code TYPE i,
lv_reason TYPE string,
lv_bodytext_b64 TYPE string,
lv_length TYPE i.
DATA: BEGIN OF ls_recipient,
emp_id TYPE string,
email TYPE string,
name TYPE string,
END OF ls_recipient.
DATA: lt_recipients_json TYPE TABLE OF string,
lv_recipients_str TYPE string.
" ✅ 1. HTTP Client 생성
TRY.
cl_http_client=>create_by_url(
EXPORTING
url = i_mail_api_url
ssl_id = 'ANONYM' " 또는 'DFAULT'
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
IF sy-subrc <> 0.
e_success = abap_false.
e_message = '메일 API URL 연결 실패'.
RAISE http_communication_failure.
ENDIF.
CATCH cx_root INTO DATA(lx_error).
e_success = abap_false.
e_message = lx_error->get_text( ).
RAISE http_communication_failure.
ENDTRY.
" ✅ 2. HTTP 메소드 및 헤더 설정
lo_http_client->request->set_method( 'POST' ).
lo_http_client->request->set_content_type( 'application/x-www-form-urlencoded' ).
lo_http_client->request->set_header_field(
name = 'charset'
value = 'UTF-8' ).
" ✅ 3. Body Text Base64 인코딩 (한글 깨짐 방지)
TRY.
DATA(lv_bodytext_raw) TYPE xstring.
" String → XSTRING (UTF-8)
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = i_bodytext
IMPORTING
buffer = lv_bodytext_raw
EXCEPTIONS
OTHERS = 1.
" XSTRING → Base64
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
input = lv_bodytext_raw
IMPORTING
output = lv_bodytext_b64.
CATCH cx_root INTO lx_error.
e_success = abap_false.
e_message = 'Body 인코딩 실패: ' && lx_error->get_text( ).
RETURN.
ENDTRY.
" ✅ 4. 수신자 목록 JSON 변환
LOOP AT t_recipients INTO DATA(ls_recip).
DATA(lv_recip_json) = |"{{ "emp_id":"{ls_recip-emp_id}", "email":"{ls_recip-email}", "name":"{ls_recip-name}" }}"| .
APPEND lv_recip_json TO lt_recipients_json.
ENDLOOP.
" ✅ 5. POST 파라미터 생성 (application/x-www-form-urlencoded)
DATA: lt_form_data TYPE tihttpnvp,
ls_form_data TYPE ihttpnvp.
" openapi=on
ls_form_data-name = 'openapi'.
ls_form_data-value = 'on'.
APPEND ls_form_data TO lt_form_data.
" empcode=admin1
ls_form_data-name = 'empcode'.
ls_form_data-value = 'admin1'. " 고정값 또는 파라미터로 변경
APPEND ls_form_data TO lt_form_data.
" to=수신자 사번
LOOP AT t_recipients INTO ls_recip.
ls_form_data-name = 'to'.
ls_form_data-value = ls_recip-emp_id.
APPEND ls_form_data TO lt_form_data.
ENDLOOP.
" subject=메일제목
ls_form_data-name = 'subject'.
ls_form_data-value = i_subject.
APPEND ls_form_data TO lt_form_data.
" bodytext=메일본문(Base64)
ls_form_data-name = 'bodytext'.
ls_form_data-value = lv_bodytext_b64.
APPEND ls_form_data TO lt_form_data.
" encodetype=UTF-8
ls_form_data-name = 'encodetype'.
ls_form_data-value = 'UTF-8'.
APPEND ls_form_data TO lt_form_data.
" certKey=ekdphandy
ls_form_data-name = 'certKey'.
ls_form_data-value = i_cert_key.
APPEND ls_form_data TO lt_form_data.
" autosubmit=Y
ls_form_data-name = 'autosubmit'.
ls_form_data-value = 'Y'.
APPEND ls_form_data TO lt_form_data.
" ✅ 6. Form Data를 URL-Encoded String으로 변환
DATA: lv_form_string TYPE string.
LOOP AT lt_form_data INTO ls_form_data.
IF sy-tabix = 1.
lv_form_string = |{ ls_form_data-name }={ cl_http_utility=>escape_url( ls_form_data-value ) }|.
ELSE.
lv_form_string = |{ lv_form_string }&{ ls_form_data-name }={ cl_http_utility=>escape_url( ls_form_data-value ) }|.
ENDIF.
ENDLOOP.
" ✅ 7. HTTP Request Body 설정
lo_http_client->request->set_cdata( lv_form_string ).
" ✅ 8. HTTP 요청 전송
TRY.
lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4 ).
IF sy-subrc <> 0.
e_success = abap_false.
e_message = '메일 발송 요청 실패'.
RAISE http_communication_failure.
ENDIF.
" ✅ 9. HTTP 응답 수신
lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4 ).
IF sy-subrc <> 0.
e_success = abap_false.
e_message = '메일 발송 응답 수신 실패'.
RAISE http_communication_failure.
ENDIF.
CATCH cx_root INTO lx_error.
e_success = abap_false.
e_message = lx_error->get_text( ).
RAISE http_communication_failure.
ENDTRY.
" ✅ 10. 응답 상태 확인
lo_http_client->response->get_status(
IMPORTING
code = lv_code
reason = lv_reason ).
lv_response = lo_http_client->response->get_cdata( ).
e_response = lv_response.
" ✅ 11. 성공 여부 판단
IF lv_code = 200 OR lv_code = 201.
" 응답 JSON 파싱 (RET_MSG 확인)
IF lv_response CS 'RET_MSG'.
e_success = abap_true.
e_message = '메일 발송 성공'.
ELSE.
e_success = abap_false.
e_message = '메일 발송 실패 - 응답: ' && lv_response.
ENDIF.
ELSE.
e_success = abap_false.
e_message = |메일 발송 실패 - HTTP { lv_code }: { lv_reason }|.
ENDIF.
" ✅ 12. HTTP 연결 종료
lo_http_client->close( ).
ENDFUNCTION.
📋 필수 구조체 정의 (SE11)
1. ZSTFI_MAIL_RECIPIENT (수신자 정보)
Structure: ZSTFI_MAIL_RECIPIENT
Component Type Length Description
-----------------------------------------------
EMP_ID CHAR 20 사원번호
EMAIL CHAR 100 이메일 주소
NAME CHAR 50 이름
RECIP_TYPE CHAR 2 TO/CC/BCC
2. ZSTFI_MAIL_ATTACH (첨부파일)
Structure: ZSTFI_MAIL_ATTACH
Component Type Length Description
-----------------------------------------------
FILENAME CHAR 255 파일명
FILEDATA XSTRING 파일 데이터(Binary)
FILESIZE INT4 파일 크기(Bytes)
MIMETYPE CHAR 100 MIME Type
🧪 테스트 프로그램
REPORT z_test_groupware_mail.
DATA: lt_recipients TYPE TABLE OF zstfi_mail_recipient,
ls_recipient TYPE zstfi_mail_recipient,
lv_success TYPE abap_bool,
lv_message TYPE string,
lv_response TYPE string.
" ✅ 수신자 추가
ls_recipient-emp_id = '1001'.
ls_recipient-email = 'user1@company.com'.
ls_recipient-name = '홍길동'.
ls_recipient-recip_type = 'TO'.
APPEND ls_recipient TO lt_recipients.
ls_recipient-emp_id = '1002'.
ls_recipient-email = 'user2@company.com'.
ls_recipient-name = '김철수'.
ls_recipient-recip_type = 'CC'.
APPEND ls_recipient TO lt_recipients.
" ✅ 메일 발송
CALL FUNCTION 'ZFI_GROUPWARE_SEND_MAIL'
EXPORTING
i_mail_api_url = 'http://groupware.company.com/api/sendmail'
i_emp_id = 'admin1'
i_subject = '테스트 메일입니다'
i_bodytext = '안녕하세요. 이것은 테스트 메일입니다.'
i_cert_key = 'ekdphandy'
IMPORTING
e_success = lv_success
e_message = lv_message
e_response = lv_response
TABLES
t_recipients = lt_recipients
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
OTHERS = 3.
IF sy-subrc = 0.
IF lv_success = abap_true.
WRITE: / '✅ 메일 발송 성공!'.
WRITE: / '응답:', lv_response.
ELSE.
WRITE: / '❌ 메일 발송 실패:', lv_message.
WRITE: / '응답:', lv_response.
ENDIF.
ELSE.
WRITE: / '❌ Function 호출 실패:', sy-subrc.
WRITE: / '메시지:', lv_message.
ENDIF.
🔧 고급 기능: 첨부파일 지원
첨부파일을 추가하려면 Function Module을 확장해야 합니다.
" ✅ 첨부파일 처리 추가 (Function Module 내부)
" 첨부파일이 있는 경우
IF t_attachments[] IS NOT INITIAL.
" Multipart/form-data 방식으로 변경
DATA: lv_boundary TYPE string VALUE 'ABAP_BOUNDARY_12345',
lv_body TYPE string.
" Boundary 설정
lo_http_client->request->set_content_type(
|multipart/form-data; boundary={ lv_boundary }| ).
" 기본 필드 추가
lv_body = |--{ lv_boundary }{ cl_abap_char_utilities=>cr_lf }|.
lv_body = |{ lv_body }Content-Disposition: form-data; name="openapi"{ cl_abap_char_utilities=>cr_lf }|.
lv_body = |{ lv_body }{ cl_abap_char_utilities=>cr_lf }on{ cl_abap_char_utilities=>cr_lf }|.
" 첨부파일 추가
LOOP AT t_attachments INTO DATA(ls_attach).
DATA(lv_attach_b64) TYPE string.
" Binary → Base64
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
input = ls_attach-filedata
IMPORTING
output = lv_attach_b64.
lv_body = |{ lv_body }--{ lv_boundary }{ cl_abap_char_utilities=>cr_lf }|.
lv_body = |{ lv_body }Content-Disposition: form-data; name="attach"; filename="{ ls_attach-filename }"{ cl_abap_char_utilities=>cr_lf }|.
lv_body = |{ lv_body }Content-Type: { ls_attach-mimetype }{ cl_abap_char_utilities=>cr_lf }|.
lv_body = |{ lv_body }Content-Transfer-Encoding: base64{ cl_abap_char_utilities=>cr_lf }|.
lv_body = |{ lv_body }{ cl_abap_char_utilities=>cr_lf }{ lv_attach_b64 }{ cl_abap_char_utilities=>cr_lf }|.
ENDLOOP.
" 마지막 Boundary
lv_body = |{ lv_body }--{ lv_boundary }--{ cl_abap_char_utilities=>cr_lf }|.
lo_http_client->request->set_cdata( lv_body ).
ENDIF.
🔐 보안 강화: HTTPS + 인증서
1. SM59 설정
Transaction: SM59
Create → HTTP Connections to External Server
RFC Destination: Z_GROUPWARE_API
Target Host: groupware.company.com
Port: 443 (HTTPS)
Path Prefix: /api
Logon & Security:
☑ SSL (Active)
SSL Certificate: DFAULT
Authentication: Basic / OAuth 2.0
2. 코드 수정 (RFC Destination 사용)
" HTTP Client 생성 (RFC Destination 사용)
CALL METHOD cl_http_client=>create_by_destination
EXPORTING
destination = 'Z_GROUPWARE_API'
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
destination_not_found = 2
destination_no_authority = 3
plugin_not_active = 4
internal_error = 5
OTHERS = 6.
📊 Java vs ABAP 기능 매핑
Java 코드ABAP 구현
| HttpClient httpClient = new DefaultHttpClient() | cl_http_client=>create_by_url() |
| HttpPost httpPost = new HttpPost(url) | set_method( 'POST' ) |
| params.add(new BasicNameValuePair(...)) | ls_form_data-name/value |
| httpPost.setEntity(new UrlEncodedFormEntity(...)) | set_cdata( lv_form_string ) |
| HttpResponse response = httpClient.execute(httpPost) | send() / receive() |
| EntityUtils.toString(respEntity) | get_cdata() |
| Hashtable<String, String> ret | e_response (JSON String) |
⚠️ 주의사항
- 한글 인코딩: Body는 반드시 Base64 인코딩 필요
- URL 파라미터: cl_http_utility=>escape_url() 사용
- 타임아웃: 기본 60초, 필요 시 set_timeout() 조정
- 에러 처리: 응답 JSON에서 RET_MSG 확인
- 인증키: certKey는 그룹웨어 관리자에게 발급 요청
✅ 체크리스트
- SE11에서 구조체 생성 (ZSTFI_MAIL_RECIPIENT)
- SE37에서 Function Module 생성
- SM59에서 RFC Destination 설정 (HTTPS)
- 그룹웨어 API URL 및 인증키 확인
- 테스트 프로그램 실행
- 메일 수신 확인
반응형
'SAP' 카테고리의 다른 글
| ACDOCA의 주요 특징 및 역할 (1) | 2025.11.26 |
|---|---|
| 젠스파크를 활용한 성능개선 - 적용 전 (1) | 2025.10.29 |
| PFCG 역할을 일괄적으로 생성하는 표준 트랜잭션 (0) | 2025.09.30 |
| SAP PP(Production Planning) 모듈 주요 테이블 (0) | 2025.09.23 |
| SAP MM(Materials Management) 모듈 주요 테이블 (0) | 2025.09.22 |