Искаженный HTML при отправке CLOB в качестве тела в UTL_SMTP

#html #oracle #email #plsql #smtp

#HTML #Oracle #Адрес электронной почты #plsql #smtp

Вопрос:

У меня есть требование отправить электронное письмо из базы данных Oracle. Это будет довольно долго, если таблица содержит более 1 тыс. строк.

Базовый код Pl / SQL выглядит следующим образом —

 PIVARHTMLMSG   CLOB;
LNUMSTART NUMBER := 1;
LNUMCHUNK NUMBER := 1900;
I NUMBER := 0;

PIVARHTMLMSG := '<HTML><BODY><P>Some Heading</P><TABLE BORDER="1"><TR><TD>ID</TD><TD>NAME</TD><TD>EMAIL</TD></TR>';

WHILE (TRUE)
LOOP
    PIVARHTMLMSG := PIVARHTMLMSG || '<TR><TD>999999</TD><TD>TEST TEST TEST</TD><TD>TEST.TEST@TEST.COM</TD></TR>';
    I := I   1;
    IF I > 1000 THEN
        EXIT;
    END IF;        
END LOOP;

WHILE LNUMSTART < NVL(DBMS_LOB.GETLENGTH(PIVARHTMLMSG), 0) LOOP
    UTL_SMTP.WRITE_DATA(lMailConn,DBMS_LOB.SUBSTR(PIVARHTMLMSG,LNUMCHUNK,LNUMSTART));
    LNUMSTART := LNUMSTART   LNUMCHUNK;  
    LNUMCHUNK := LEAST(LNUMCHUNK,DBMS_LOB.GETLENGTH(PIVARHTMLMSG) -LNUMCHUNK);
END LOOP;
  

Электронное письмо отображается следующим образом —

введите описание изображения здесь

Что может быть возможной причиной такого поведения?

Комментарии:

1. Пожалуйста, покажите свой полный код, который отправляет почту.

Ответ №1:

Вы не предоставляете самый важный материал, например, вызовы UTL_SMTP процедур.

Взгляните на мою процедуру отправки почты:

 SUBTYPE T_MAIL_PRIORITY IS INTEGER;
PRIORITY_HIGH           CONSTANT INTEGER := 1;
PRIORITY_NORMAL         CONSTANT INTEGER := 3;
PRIORITY_LOW            CONSTANT INTEGER := 5;

PROCEDURE SendMail(
    Subject IN VARCHAR2, 
    Message IN OUT CLOB, 
    ToMail IN VARCHAR2,   
    FromMail IN VARCHAR2, FromName IN VARCHAR2,
    Attachment IN OUT CLOB, FileName IN VARCHAR2,
    Priority IN T_MAIL_PRIORITY) IS

    MIME_BOUNDARY           CONSTANT VARCHAR2(50) := '====Multipart.Boundary.689464861147414354====';
    MIME_MIXED              CONSTANT VARCHAR2(50) := 'multipart/mixed;';
    MIME_TEXT               CONSTANT VARCHAR2(50) := 'text/plain;';
    MIME_HTML               CONSTANT VARCHAR2(50) := 'text/html;';  

    con UTL_SMTP.connection;
    ret UTL_SMTP.reply;
    Charset VARCHAR2(20);

    ClobLen PLS_INTEGER;
    amount BINARY_INTEGER := 8192;
    buffer VARCHAR2(16384);
    offset PLS_INTEGER := 1;
    isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '<(html)|(body)', 'i');

BEGIN

    SELECT UTL_I18N.MAP_CHARSET(VALUE)
    INTO Charset
    FROM nls_database_parameters
    WHERE parameter = 'NLS_CHARACTERSET';

    -- setup mail header
    con := UTL_SMTP.OPEN_CONNECTION('mailhost', 25);
    ret := UTL_SMTP.helo(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN'));
    ret := UTL_SMTP.Mail(con, FromMail);
    ret := UTL_SMTP.rcpt(con, ToMail);
    ret := UTL_SMTP.open_data(con);

    UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||FromMail||'>'||UTL_TCP.CRLF);
    UTL_SMTP.write_data(con, 'To: '||ToMail||UTL_TCP.CRLF);
    UTL_SMTP.write_data(con, 'Date: '||TO_CHAR(CURRENT_TIMESTAMP, 'Dy, DD Mon YYYY hh24:mi:ss TZHTZM', 'NLS_DATE_LANGUAGE = American')||UTL_TCP.CRLF);      
    UTL_SMTP.write_data(con, 'Subject: '||Subject||UTL_TCP.CRLF);
    UTL_SMTP.write_data(con, 'X-Priority: '||Priority||UTL_TCP.CRLF);

    IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
        UTL_SMTP.write_data(con, 'Mime-Version: 1.0' || UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, 'Content-Type: '||MIME_MIXED||' boundary="'||MIME_BOUNDARY||'"' || UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, 'This is a multipart message in MIME format.' || UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
    END IF;

    IF isHTML THEN
        UTL_SMTP.write_data(con, 'Content-type: '||MIME_HTML||' charset='||Charset || UTL_TCP.CRLF);
    ELSE 
        UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT||' charset='||Charset || UTL_TCP.CRLF);
    END IF;

    -- Mail Body
    UTL_SMTP.write_data(con, UTL_TCP.CRLF);
    ClobLen := DBMS_LOB.GETLENGTH(Message);
    LOOP
        EXIT WHEN offset > ClobLen;
        DBMS_LOB.READ(Message, amount, offset, BUFFER);
        UTL_SMTP.write_raw_data(con, UTL_RAW.cast_to_raw(BUFFER));
        offset := offset   amount;
    END LOOP;   
    UTL_SMTP.write_data(con, UTL_TCP.CRLF);

    IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
        -- Mail Attachment
        UTL_SMTP.write_data(con, UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, 'Content-Type: '||MIME_TEXT||' name="'||Filename||'"'|| UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="'||Filename||'"'|| UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, UTL_TCP.CRLF);

        offset := 1;
        ClobLen := DBMS_LOB.GETLENGTH(Attachment);
        LOOP
            EXIT WHEN offset > ClobLen;
            DBMS_LOB.READ(Attachment, amount, offset, BUFFER);
            UTL_SMTP.write_raw_data(con, UTL_RAW.cast_to_raw(BUFFER));
            offset := offset   amount;
        END LOOP;
        UTL_SMTP.write_data(con, UTL_TCP.CRLF);
        UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY||'--' || UTL_TCP.CRLF);
    END IF;

    -- finish mail
    ret := UTL_SMTP.close_data(con);
    ret := UTL_SMTP.quit(con);

EXCEPTION
    WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
        UTL_SMTP.quit(con);
        RAISE;
END SendMail;
  

Не пропускайте «пустые» UTL_SMTP.write_data(con, UTL_TCP.CRLF); вызовы, они необходимы для правильной структуры вашей почты.

Также строка UTL_SMTP.write_data(con, 'This is a multipart message in MIME format.' || UTL_TCP.CRLF); выглядит неуместной — она важна для правильного вывода!

Вот результат моего теста с использованием вашего сообщения.

введите описание изображения здесь

Комментарии:

1. Не повезло, все тот же результат, что и на скриншоте.

2. Нет необходимости в самом коде, проблема заключается в почтовом сервере Outlook, а не в Oracle. Обратитесь к этой ссылке для получения дополнительной информации. asktom.oracle.com/pls/asktom /…

3. Странно, некоторое время назад у меня была такая же проблема с неправильно отформатированными письмами, но эта процедура решила ее. Возможно, стоит добавить HTML-документ в качестве вложения, см. Мою обновленную процедуру.

4. Требуется для html-почты, не удается отправить его как вложение. В любом случае, спасибо за ваши данные.