|
1 | 1 | create or replace package body mailgun_pkg is
|
2 |
| -/* mailgun API v0.4 |
| 2 | +/* mailgun API v0.4.2 |
3 | 3 | by Jeffrey Kemp
|
4 | 4 | */
|
5 | 5 |
|
6 |
| -g_public_api_key constant varchar2(200) := ''; --TODO: put your public API key here |
7 |
| -g_private_api_key constant varchar2(200) := ''; --TODO: put your private API key here |
8 |
| -g_my_domain constant varchar2(200) := ''; --TODO: put your domain here |
| 6 | +-- If you get "PLS-00322: declaration of a constant 'x' must contain an initialization assignment", |
| 7 | +-- it's probably because you forgot to edit the constants below. |
| 8 | + |
| 9 | +g_public_api_key constant varchar2(200) /*:= 'TODO: put your public API key here' */; |
| 10 | +g_private_api_key constant varchar2(200) /*:= 'TODO: put your private API key here' */; |
| 11 | +g_my_domain constant varchar2(200) /*:= 'TODO: put your domain here' */; |
9 | 12 | g_api_url constant varchar2(200) := 'https://api.mailgun.net/v3/'; --TODO: change this if you are using reverse proxy method
|
10 | 13 | g_wallet_path constant varchar2(1000) := ''; --TODO: put your wallet path here if using Oracle wallet
|
11 | 14 | g_wallet_password constant varchar2(1000) := ''; --TODO: put your wallet password here if using Oracle wallet
|
12 | 15 |
|
13 |
| -crlf constant varchar2(50) := chr(13) || chr(10); |
14 |
| -boundary constant varchar2(100) := '-----zdkgyl5aalom86symjq9y81s2jtorr'; |
| 16 | +boundary constant varchar2(100) := '-----n8vtmn6973vyrnsw1agnxs7gzc4e1r'; |
15 | 17 | max_recipients constant integer := 1000; -- mailgun limitation for recipient variables
|
16 | 18 | queue_name constant varchar2(30) := sys_context('userenv','current_schema')||'.mailgun_queue';
|
17 | 19 | queue_table constant varchar2(30) := sys_context('userenv','current_schema')||'.mailgun_queue_tab';
|
@@ -162,6 +164,10 @@ begin
|
162 | 164 | assert(p_email is not null, 'add_recipient: p_email cannot be null');
|
163 | 165 | assert(p_send_by is not null, 'add_recipient: p_send_by cannot be null');
|
164 | 166 | assert(p_send_by in ('to','cc','bcc'), 'p_send_by must be to/cc/bcc');
|
| 167 | + |
| 168 | + -- don't allow a list of email addresses in one call |
| 169 | + assert(instr(p_email,',')=0, 'add_recipient: p_email cannot contain commas (,)'); |
| 170 | + assert(instr(p_email,';')=0, 'add_recipient: p_email cannot contain semicolons (;)'); |
165 | 171 |
|
166 | 172 | name := nvl(p_name, trim(p_first_name || ' ' || p_last_name));
|
167 | 173 |
|
@@ -362,30 +368,35 @@ procedure send_email (p_payload in out nocopy t_mailgun_email) is
|
362 | 368 | resp utl_http.resp;
|
363 | 369 | my_scheme varchar2(256);
|
364 | 370 | my_realm varchar2(256);
|
365 |
| - buf varchar2(32767); |
366 | 371 | attachment_size integer;
|
367 | 372 | resp_text varchar2(32767);
|
368 | 373 | recipient_count integer := 0;
|
369 | 374 | attachment_count integer := 0;
|
370 | 375 | log mailgun_email_log%rowtype;
|
371 | 376 |
|
372 | 377 | procedure append_recipient (rcpt_list in out varchar2, r in t_mailgun_recipient) is
|
373 |
| - begin |
374 |
| - |
| 378 | + begin |
375 | 379 | if rcpt_list is not null then
|
376 |
| - rcpt_list := rcpt_list || ', '; |
| 380 | + rcpt_list := rcpt_list || ','; |
377 | 381 | end if;
|
378 | 382 | rcpt_list := rcpt_list || r.email_spec;
|
379 |
| - |
| 383 | + end append_recipient; |
| 384 | + |
| 385 | + procedure add_recipient_variable (r in t_mailgun_recipient) is |
| 386 | + begin |
380 | 387 | apex_json.open_object(r.email);
|
381 | 388 | apex_json.write('email', r.email);
|
382 | 389 | apex_json.write('name', r.name);
|
383 | 390 | apex_json.write('first_name', r.first_name);
|
384 | 391 | apex_json.write('last_name', r.last_name);
|
385 | 392 | apex_json.write('id', r.id);
|
386 | 393 | apex_json.close_object;
|
387 |
| - |
388 |
| - end append_recipient; |
| 394 | + end add_recipient_variable; |
| 395 | + |
| 396 | + procedure append_header (buf in varchar2) is |
| 397 | + begin |
| 398 | + dbms_lob.writeappend(header, length(buf), buf); |
| 399 | + end append_header; |
389 | 400 |
|
390 | 401 | procedure log_response is
|
391 | 402 | -- needs to commit the log entry independently of calling transaction
|
@@ -446,72 +457,79 @@ begin
|
446 | 457 |
|
447 | 458 | if p_payload.to_email is not null then
|
448 | 459 | assert(recipient_count = 0, 'cannot mix multiple recipients with to_email parameter');
|
449 |
| - if p_payload.to_email like '% <%>%' then |
450 |
| - recipients_to := p_payload.to_email; |
451 |
| - else |
| 460 | + |
| 461 | + if p_payload.to_name is not null |
| 462 | + and p_payload.to_email not like '% <%>%' |
| 463 | + and instr(p_payload.to_email, ',') = 0 |
| 464 | + and instr(p_payload.to_email, ';') = 0 then |
| 465 | + -- to_email is just a single, simple email address, and we have a to_name |
452 | 466 | recipients_to := nvl(p_payload.to_name, p_payload.to_email) || ' <' || p_payload.to_email || '>';
|
| 467 | + else |
| 468 | + -- to_email is a formatted name+email, or a list, or we don't have any to_name |
| 469 | + recipients_to := replace(p_payload.to_email, ';', ','); |
453 | 470 | end if;
|
| 471 | + |
454 | 472 | end if;
|
455 | 473 |
|
456 |
| - recipients_cc := p_payload.cc; |
457 |
| - recipients_bcc := p_payload.bcc; |
| 474 | + recipients_cc := replace(p_payload.cc, ';', ','); |
| 475 | + recipients_bcc := replace(p_payload.bcc, ';', ','); |
| 476 | + |
| 477 | + if recipient_count > 0 then |
| 478 | + for i in 1..recipient_count loop |
| 479 | + -- construct the comma-delimited recipient lists |
| 480 | + case p_payload.recipient(i).send_by |
| 481 | + when 'to' then |
| 482 | + append_recipient(recipients_to, p_payload.recipient(i)); |
| 483 | + when 'cc' then |
| 484 | + append_recipient(recipients_cc, p_payload.recipient(i)); |
| 485 | + when 'bcc' then |
| 486 | + append_recipient(recipients_bcc, p_payload.recipient(i)); |
| 487 | + end case; |
| 488 | + end loop; |
| 489 | + end if; |
458 | 490 |
|
459 |
| - begin |
460 |
| - apex_json.initialize_clob_output; |
461 |
| - apex_json.open_object; |
| 491 | + assert(recipients_to is not null, 'send_email: recipients list cannot be empty'); |
| 492 | + |
| 493 | + dbms_lob.createtemporary(header, false, dbms_lob.call); |
| 494 | + |
| 495 | + append_header(crlf |
| 496 | + || form_field('from', sender) |
| 497 | + || form_field('h:Reply-To', p_payload.reply_to) |
| 498 | + || form_field('to', recipients_to) |
| 499 | + || form_field('cc', recipients_cc) |
| 500 | + || form_field('bcc', recipients_bcc) |
| 501 | + || form_field('o:tag', p_payload.tag) |
| 502 | + || form_field('subject', p_payload.subject) |
| 503 | + ); |
462 | 504 |
|
463 |
| - if recipient_count > 0 then |
| 505 | + if recipient_count > 0 then |
| 506 | + begin |
| 507 | + -- construct the recipient variables json object |
| 508 | + apex_json.initialize_clob_output; |
| 509 | + apex_json.open_object; |
464 | 510 | for i in 1..recipient_count loop
|
| 511 | + add_recipient_variable(p_payload.recipient(i)); |
| 512 | + end loop; |
| 513 | + apex_json.close_object; |
465 | 514 |
|
466 |
| - case p_payload.recipient(i).send_by |
467 |
| - when 'to' then |
468 |
| - append_recipient(recipients_to, p_payload.recipient(i)); |
469 |
| - when 'cc' then |
470 |
| - append_recipient(recipients_cc, p_payload.recipient(i)); |
471 |
| - when 'bcc' then |
472 |
| - append_recipient(recipients_bcc, p_payload.recipient(i)); |
473 |
| - end case; |
474 |
| - |
475 |
| - end loop; |
476 |
| - end if; |
477 |
| - |
478 |
| - apex_json.close_object; |
479 |
| - |
480 |
| - assert(recipients_to is not null, 'send_email: recipients list cannot be empty'); |
481 |
| - |
482 |
| - dbms_lob.createtemporary(header, false, dbms_lob.call); |
483 |
| - |
484 |
| - header := crlf |
485 |
| - || form_field('from', sender) |
486 |
| - || form_field('h:Reply-To', p_payload.reply_to) |
487 |
| - || form_field('to', recipients_to) |
488 |
| - || form_field('cc', recipients_cc) |
489 |
| - || form_field('bcc', recipients_bcc) |
490 |
| - || form_field('o:tag', p_payload.tag) |
491 |
| - || form_field('subject', p_payload.subject) |
492 |
| - || field_header('recipient-variables'); |
493 |
| - |
494 |
| - dbms_lob.append(header, apex_json.get_clob_output); |
495 |
| - |
496 |
| - apex_json.free_output; |
497 |
| - |
498 |
| - exception |
499 |
| - when others then |
500 |
| - apex_json.free_output; |
501 |
| - raise; |
502 |
| - end; |
| 515 | + append_header(field_header('recipient-variables')); |
| 516 | + dbms_lob.append(header, apex_json.get_clob_output); |
| 517 | + |
| 518 | + apex_json.free_output; |
| 519 | + exception |
| 520 | + when others then |
| 521 | + apex_json.free_output; |
| 522 | + raise; |
| 523 | + end; |
| 524 | + end if; |
503 | 525 |
|
504 | 526 | if p_payload.mail_headers is not null then
|
505 |
| - buf := render_mail_headers(p_payload.mail_headers); |
506 |
| - dbms_lob.writeappend(header, length(buf), buf); |
| 527 | + append_header(render_mail_headers(p_payload.mail_headers)); |
507 | 528 | end if;
|
508 | 529 |
|
509 |
| - buf := crlf || field_header('html'); |
510 |
| - dbms_lob.writeappend(header, length(buf), buf); |
511 |
| - |
| 530 | + append_header(field_header('html')); |
512 | 531 | dbms_lob.append(header, p_payload.message);
|
513 |
| - |
514 |
| - dbms_lob.writeappend(header, length(crlf), crlf); |
| 532 | + append_header(crlf); |
515 | 533 |
|
516 | 534 | footer := '--' || boundary || '--';
|
517 | 535 |
|
|
0 commit comments