CftClub.ru
Клуб специалистов ЦФТ-Банк

Рассылка сообщений на e-mail
На страницу Пред.  1, 2, 3
 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Справочник PL/PLUS: Функции, примеры, приёмы
Предыдущая тема :: Следующая тема  
Автор Сообщение
belyansky
Участник со стажем


Вступление в Клуб: 22.10.2007
СообщениеЧт Сен 18, 2008 08:36    Ответить с цитатой
Полезность: Нет оценки
files(1).file_path := 'C:\TEST\' - так тоже не выходит...
Да, в эксплуатации файлик будет хвататься с сервера, но пока отрабатываю с локального диска, перенаправить на сервер уже будет не проблемой.
dnk_dz
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеЧт Сен 18, 2008 08:40    Ответить с цитатой
Полезность: 1
belyansky пишет:
files(1).file_path := 'C:\TEST\' - так тоже не выходит...
Да, в эксплуатации файлик будет хвататься с сервера, но пока отрабатываю с локального диска, перенаправить на сервер уже будет не проблемой.

Чтобы отправить файл с локального диска его сначала нужно скопировать на сервер. Процедура отправки вложения работает только с файлами на сервере.
belyansky
Участник со стажем


Вступление в Клуб: 22.10.2007
СообщениеЧт Сен 18, 2008 10:19    Ответить с цитатой
Полезность: Нет оценки
да, с сервера файл цепляется, вернее он находится и открывается. Спасибо за совет. Но в итоге получилось так, что содержимое файла было перенесено в тело письма. а нет возможности подсоединять сам файл к письму????
ranov
Участник


Вступление в Клуб: 24.06.2008
СообщениеЧт Окт 02, 2008 10:00    Ответить с цитатой
Полезность: Нет оценки
использую предложенную процедуру send_mail возникает ошибка:
"Невозможно отправить электронное письмо по следующим причинам: ORA-29279: SMTP permanent error: 501 5.1.7 Bad sender address syntax"

что не так?
Вызываю так
send_email('192.168.1.111',25, 'Overdrafts', 'lll@domain.ru', utl_raw.cast_to_raw('tema'), utl_raw.cast_to_raw('text'));
Спасибо
dnk_dz
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеЧт Окт 02, 2008 10:54    Ответить с цитатой
Полезность: Нет оценки
ranov пишет:
использую предложенную процедуру send_mail возникает ошибка:
"Невозможно отправить электронное письмо по следующим причинам: ORA-29279: SMTP permanent error: 501 5.1.7 Bad sender address syntax"

что не так?
Вызываю так
send_email('192.168.1.111',25, 'Overdrafts', 'lll@domain.ru', utl_raw.cast_to_raw('tema'), utl_raw.cast_to_raw('text'));
Спасибо


Посмотрите, есть ли в коде send_mail следующая строка:
Код:
v_from := 'From: "'||p_from||'"';
ranov
Участник


Вступление в Клуб: 24.06.2008
СообщениеЧт Окт 02, 2008 16:53    Ответить с цитатой
Полезность: Нет оценки
Да есть. Я полностью взял пример и исправил только адреса и домен. Возможно, что то с сервером... но что? Пакеты доступны и собраны, доступ к почтовому серверу есть.
dnk_dz
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеЧт Окт 02, 2008 17:48    Ответить с цитатой
Полезность: Нет оценки
ranov пишет:
Да есть. Я полностью взял пример и исправил только адреса и домен. Возможно, что то с сервером... но что? Пакеты доступны и собраны, доступ к почтовому серверу есть.


Тогда смотрите настройки почтового сервера. Может, ему недостаточно посылать "FROM:". В интернете есть подробное описание данной проблемы.
dnk_dz
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеСр Дек 24, 2008 07:04    Ответить с цитатой
Полезность: 3
Доработал пакет отправки на e-mail, представленный здесь уважаемым SkyLynx.
Суть доработки:
1. Добавлена возможность отправлять большой текст (теоретически, до 4GB Shocked )
2. Исправлена процедура отправки файлов в аттаче, т.к. некоторые антивирусы и фаерволы не пропускали бинарные вложения, сделанные с помощью данного пакета. Размер файла тоже может быть до 4GB.
3. Сделана одна универсальная процедура отправки сообщения и файла. Собственно вот она:

Код:
   procedure send_mail(
      sender         in varchar2(2000),      -- отправитель
      recipients      in varchar2(32000),      -- получатели
      subject         in varchar2(2000),      -- тема
      msg            in clob,                  -- сообщение
      file_path      in varchar2(256),       -- путь к файлу для отправки
      file_name      in varchar2(256)         -- имя файла для отправки
   );
dnk_dz
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеСр Дек 24, 2008 07:05    Ответить с цитатой
Полезность: Нет оценки
Локальное описание:
Код:

FUNCTION get_address(addr_list IN OUT VARCHAR2) RETURN VARCHAR2 IS
   addr VARCHAR2(256);
   i    pls_integer;

   FUNCTION lookup_unquoted_char(
      str  IN VARCHAR2,
      chrs IN VARCHAR2
   ) RETURN pls_integer IS
      c            VARCHAR2(5);
      i            pls_integer;
      len          pls_integer;
      inside_quote BOOLEAN;
   BEGIN
      inside_quote := false;
      i := 1;
      len := length(str);
      WHILE (i <= len) LOOP
         c := substr(str, i, 1);
         IF (inside_quote) THEN
            IF (c = '"') THEN
               inside_quote := false;
            ELSIF (c = '\') THEN
               i := i + 1; -- Skip the quote character
            END IF;
            GOTO next_char;
         END IF;
         IF (c = '"') THEN
            inside_quote := true;
            GOTO next_char;
         END IF;
         IF (instr(chrs, c) >= 1) THEN
            RETURN i;
         END IF;
         <<next_char>>
         i := i + 1;
      END LOOP;
      RETURN 0;
   END;

BEGIN
   addr_list := ltrim(addr_list);
   i := lookup_unquoted_char(addr_list, ',;');
   IF (i >= 1) THEN
      addr      := substr(addr_list, 1, i - 1);
      addr_list := substr(addr_list, i + 1);
   ELSE
      addr := addr_list;
      addr_list := '';
   END IF;

   i := lookup_unquoted_char(addr, '<');
   IF (i >= 1) THEN
      addr := substr(addr, i + 1);
      i := instr(addr, '>');
      IF (i >= 1) THEN
         addr := substr(addr, 1, i - 1);
      END IF;
   END IF;
   RETURN addr;
END;

PROCEDURE write_mime_header(
   conn  IN OUT NOCOPY utl_smtp.connection,
   name  IN VARCHAR2,
   value IN VARCHAR2
) IS
BEGIN
   if mail_charset is not null then
      utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(convert(name || ': ' || value || utl_tcp.CRLF,mail_charset)));
   else
      utl_smtp.write_data(conn, name || ': ' || value || utl_tcp.CRLF);
   end if;
END;

-- boundary.
PROCEDURE write_boundary(
   conn  IN OUT NOCOPY utl_smtp.connection,
   last  IN            BOOLEAN DEFAULT FALSE
) IS
BEGIN
   IF (last) THEN
      utl_smtp.write_data(conn, LAST_BOUNDARY);
   ELSE
      utl_smtp.write_data(conn, FIRST_BOUNDARY);
   END IF;
END;

------------------------------------------------------------------------
PROCEDURE mail(
   sender     IN VARCHAR2,
   recipients IN VARCHAR2,
   subject    IN VARCHAR2,
   message    IN VARCHAR2,
   mime_type  IN VARCHAR2 default 'text/plain'
) IS
   conn utl_smtp.connection;
BEGIN
   conn := begin_mail(sender, recipients, subject, mime_type);
   write_text(conn, message);
   end_mail(conn);
END;

------------------------------------------------------------------------
FUNCTION begin_mail(
   sender     IN VARCHAR2,
   recipients IN VARCHAR2,
   subject    IN VARCHAR2,
   mime_type  IN VARCHAR2    DEFAULT 'text/plain',
   priority   IN PLS_INTEGER DEFAULT NULL
) RETURN utl_smtp.connection IS
   conn utl_smtp.connection;
BEGIN
   if smtp_port is null then
      smtp_port:=25;
   end if;
   if smtp_domain is null then
      if instr(smtp_host,'.')>0 then
         smtp_domain:=substr(smtp_host,instr(smtp_host,'.')+1);
      end if;
   end if;
   if instr(upper(mime_type),'CHARSET')>0 then
      if instr(upper(mime_type),'WINDOWS-1251')>0 then
         mail_charset:='CL8MSWIN1251';
      end if;
   end if;
   conn := begin_session;
   begin_mail_in_session(conn, sender, recipients, subject, mime_type, priority);
   RETURN conn;
END;

------------------------------------------------------------------------
PROCEDURE write_text(
   conn    IN OUT NOCOPY utl_smtp.connection,
   message IN VARCHAR2
) IS
BEGIN
   if mail_charset is not null then
      utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(convert(message,mail_charset)));
   else
      utl_smtp.write_data(conn, message);
   end if;
END;

------------------------------------------------------------------------
PROCEDURE write_mb_text(
   conn    IN OUT NOCOPY utl_smtp.connection,
   message IN            VARCHAR2
) IS
BEGIN
   if mail_charset is not null then
      utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(convert(message,mail_charset)));
   else
      utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
   end if;
END;

------------------------------------------------------------------------
PROCEDURE write_raw(
   conn    IN OUT NOCOPY utl_smtp.connection,
   message IN RAW
) IS
BEGIN
   utl_smtp.write_raw_data(conn, message);
END;

------------------------------------------------------------------------
PROCEDURE attach_text(
   conn         IN OUT NOCOPY utl_smtp.connection,
   data         IN VARCHAR2,
   mime_type    IN VARCHAR2 DEFAULT 'text/plain',
   inline       IN BOOLEAN  DEFAULT TRUE,
   filename     IN VARCHAR2 DEFAULT NULL,
   last         IN BOOLEAN  DEFAULT FALSE
) IS
BEGIN
   begin_attachment(conn, mime_type, inline, filename);
   write_text(conn, data);
   end_attachment(conn, last);
END;

------------------------------------------------------------------------
PROCEDURE attach_base64(
   conn         IN OUT NOCOPY utl_smtp.connection,
   data         IN RAW,
   mime_type    IN VARCHAR2 DEFAULT 'application/octet',
   inline       IN BOOLEAN  DEFAULT TRUE,
   filename     IN VARCHAR2 DEFAULT NULL,
   last         IN BOOLEAN  DEFAULT FALSE
) IS
   i   PLS_INTEGER;
   len PLS_INTEGER;
BEGIN
   begin_attachment(conn, mime_type, inline, filename, 'base64');
   -- Split the Base64-encoded attachment into multiple lines
   i   := 1;
   len := utl_raw.length(data);
   WHILE (i < len) LOOP
      IF (i + MAX_BASE64_LINE_WIDTH < len) THEN
         utl_smtp.write_raw_data(conn,
         utl_encode.base64_encode(utl_raw.substr(data, i, MAX_BASE64_LINE_WIDTH)));
      ELSE
         utl_smtp.write_raw_data(conn,
         utl_encode.base64_encode(utl_raw.substr(data, i)));
      END IF;
      utl_smtp.write_data(conn, utl_tcp.CRLF);
      i := i + MAX_BASE64_LINE_WIDTH;
   END LOOP;
   end_attachment(conn, last);
END;

------------------------------------------------------------------------
PROCEDURE begin_attachment(
   conn         IN OUT NOCOPY utl_smtp.connection,
   mime_type    IN VARCHAR2 DEFAULT 'text/plain',
   inline       IN BOOLEAN  DEFAULT TRUE,
   filename     IN VARCHAR2 DEFAULT NULL,
   transfer_enc IN VARCHAR2 DEFAULT NULL) IS
BEGIN
   write_boundary(conn);
   write_mime_header(conn, 'Content-Type', mime_type);

   IF (filename IS NOT NULL) THEN
      IF (inline) THEN
         write_mime_header(conn, 'Content-Disposition','inline; filename="'||filename||'"');
      ELSE
         write_mime_header(conn, 'Content-Disposition','attachment; filename="'||filename||'"');
      END IF;
   END IF;

   IF (transfer_enc IS NOT NULL) THEN
      write_mime_header(conn, 'Content-Transfer-Encoding', transfer_enc);
   END IF;
   utl_smtp.write_data(conn, utl_tcp.CRLF);
END;

------------------------------------------------------------------------
PROCEDURE end_attachment(
   conn IN OUT NOCOPY utl_smtp.connection,
   last IN BOOLEAN DEFAULT FALSE
) IS
BEGIN
   utl_smtp.write_data(conn, utl_tcp.CRLF);
   IF (last) THEN
      write_boundary(conn, last);
   END IF;
END;

------------------------------------------------------------------------
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
   end_mail_in_session(conn);
   end_session(conn);
END;

------------------------------------------------------------------------
FUNCTION begin_session RETURN utl_smtp.connection IS
   conn utl_smtp.connection;
BEGIN
   -- open SMTP connection
   conn := utl_smtp.open_connection(smtp_host, smtp_port);
--   utl_smtp.helo(conn, smtp_domain);
   utl_smtp.ehlo(conn, smtp_domain);

   -- авторизация
/*
   utl_smtp.command(conn, 'AUTH LOGIN');
   utl_smtp.command(conn, utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('TrapezinA'))));
   utl_smtp.command(conn, utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('password'))));
*/
   RETURN conn;
END;

------------------------------------------------------------------------
PROCEDURE begin_mail_in_session(
   conn       IN OUT NOCOPY utl_smtp.connection,
   sender     IN VARCHAR2,
   recipients IN VARCHAR2,
   subject    IN VARCHAR2,
   mime_type  IN VARCHAR2  DEFAULT 'text/plain',
   priority   IN PLS_INTEGER DEFAULT NULL) IS
   my_recipients VARCHAR2(32767) := recipients;
   my_sender     VARCHAR2(32767) := sender;
BEGIN
   utl_smtp.mail(conn, get_address(my_sender));
   WHILE (my_recipients IS NOT NULL) LOOP
      utl_smtp.rcpt(conn, get_address(my_recipients));
   END LOOP;
   -- Start body of email
   utl_smtp.open_data(conn);
   -- Set "From" MIME header
   write_mime_header(conn, 'From', sender);
   -- Set "To" MIME header
   write_mime_header(conn, 'To', recipients);
   -- Set "Subject" MIME header
   write_mime_header(conn, 'Subject', subject);
   -- Set "Content-Type" MIME header
   write_mime_header(conn, 'Content-Type', mime_type);
   -- Set "X-Mailer" MIME header
   write_mime_header(conn, 'X-Mailer', MAILER_ID);
   -- Set priority:
   --   High      Normal       Low
   --   1     2     3     4     5
   IF (priority IS NOT NULL) THEN
      write_mime_header(conn, 'X-Priority', priority);
   END IF;

   -- Send an empty line to denotes end of MIME headers and
   -- beginning of message body.
   utl_smtp.write_data(conn, utl_tcp.CRLF);

   IF (mime_type LIKE 'multipart/mixed%') THEN
      write_text(conn, 'This is a multi-part message in MIME format.'||utl_tcp.crlf);
   END IF;
END;

  ------------------------------------------------------------------------
  PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection) IS
  BEGIN
    utl_smtp.close_data(conn);
  END;

------------------------------------------------------------------------
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
   utl_smtp.quit(conn);
END;

-- отправить письмо с вложением файла
-- файл должен существовать на локальном диске!
procedure send_mail_with_attach(
   sender     IN VARCHAR2, -- отправитель
   recipients IN VARCHAR2,   -- получатели
   subject    IN VARCHAR2, -- тема сообщения
   message    IN VARCHAR2, -- тело сообщения
   file_path  IN VARCHAR2, -- путь к файлу
   file_name  IN VARCHAR2, -- имя файла
   mime_type  IN VARCHAR2 DEFAULT 'text/plain'
) is
f      number;
dat   raw(2000);
conn   utl_smtp.connection;
begin
   conn := begin_mail(
      sender,
      recipients,
      subject,
      MULTIPART_MIME_TYPE||' charset="windows-1251"'
   );
   -- положим тело сообщения
   if message is not null then
      attach_text(conn, message, mime_type);
   end if;
   begin
      f:=STDIO.OPEN(file_path, file_name, 'r');
   exception
   when others then
      if sqlcode in (-4061,-6508) then raise; end if;
--      RTL.DEBUG_PIPE('Ошибка при открытии файла: '||SQLERRM,0);
   end;
   if STDIO.IS_OPEN(f) then
      begin_attachment(conn, mime_type, FALSE, file_name);
      loop
         if stdio.f_read(f, dat, 2000)>0 then
            write_raw(conn, dat);
         else
            exit;
         end if;
      end loop;
      stdio.close(f);
      end_attachment(conn, true);
   end if;
   end_mail(conn);
end;

-- отправить письмо с вложенными файлами
-- файлы должены существовать на локальном диске сервера!
procedure send_mail_with_attachments(
   sender     IN VARCHAR2, -- отправитель
   recipients IN VARCHAR2,   -- получатели
   subject    IN VARCHAR2, -- тема сообщения
   message    IN VARCHAR2, -- тело сообщения
   files  IN attach_tbl, -- файлы для вложения
   mime_type  IN VARCHAR2 DEFAULT 'text/plain'
) is
f      number;
dat   raw(2000);
conn   utl_smtp.connection;
b_att   boolean   :=   false;
begin
   conn := begin_mail(
      sender,
      recipients,
      subject,
      MULTIPART_MIME_TYPE||' charset="windows-1251"'
   );
   -- положим тело сообщения
   if message is not null then
      attach_text(conn, message, mime_type);
   end if;
   if files.count > 0 then   -- есть список вложений
      for idx in files.first..files.last loop
         begin
            f := STDIO.OPEN(trim(files(idx).file_path), trim(files(idx).file_name), 'r');
         exception
         when others then
            if sqlcode in (-4061,-6508) then raise; end if;
            RTL.DEBUG('UTL_SMTP$: sqlerrm = '||sqlerrm,3,true);
            goto end$loop$1;   -- файл не смог открыться, берем следующий
         end;
         if STDIO.IS_OPEN(f) then
            RTL.DEBUG('UTL_SMTP$: add attach name = '||trim(files(idx).file_name),3,true);
            begin_attachment(conn, mime_type, FALSE, trim(files(idx).file_name));
            if not b_att then
               b_att := true;
            end if;
            loop
               if stdio.f_read(f, dat, 2000)>0 then
                  write_raw(conn, dat);
               else
                  exit;
               end if;
            end loop;
            stdio.close(f);
         end if;
         <<end$loop$1>>
         null;
      end loop;
   end if;
   if b_att then
      end_attachment(conn, true);
   end if;
   end_mail(conn);
end;


-----------------------------------------------------------------
-- отправка сообщения
-- получатели разделяются знаками "," или ";"
procedure send_mail(
      sender         in varchar2(2000),      -- отправитель
      recipients      in varchar2(32000),      -- получатели
      subject         in varchar2(2000),      -- тема
      msg            in clob,                  -- сообщение
      file_path      in varchar2(256),       -- путь к файлу для отправки
      file_name      in varchar2(256)         -- имя файла для отправки
) is
   conn            utl_smtp.connection;
   msg_len         number;
   pos            number                   := 1;
   bytes_o_data   constant number          := 32767;
   offset         number                   := bytes_o_data;
   first_loop      boolean                  := true;
   attach_html      boolean                  := false;
   str            varchar2(32767);
   data            blob;
   src_file         number;
   buff            raw(2000);
   bytes            number;
begin
   conn      :=  begin_mail(sender, recipients, subject, MULTIPART_MIME_TYPE||' charset="windows-1251"');
   msg_len   := dbms_lob.getlength(msg);
   
   if msg_len > 0 then
      begin_attachment(conn,  'text/html; charset="windows-1251"', true, null);
      
      while pos < msg_len
      loop
         str := dbms_lob.substr(msg, offset, pos);
         if first_loop then
            first_loop := false;
            if instr(lower(str), '<html>') = 0 then
               -- Если простой текст, то добавим заголовки html
               attach_html := true;
               write_text(conn, '<html>');
               write_text(conn, '<head>');
               write_text(conn, '<title>');
               write_text(conn, subject);
               write_text(conn, '</title>');
               write_text(conn, '</head>');
               write_text(conn, '<body>');
            end if;
         end if;
         write_text(conn, str);
         pos      := pos + offset;
         offset   := least(bytes_o_data, msg_len - offset);
      end loop;
      if attach_html then
         write_text(conn, '</body>');
         write_text(conn, '</html>');
      end if;
      end_attachment(conn, false);   
   end if;


   if file_name is not null then      
      dbms_lob.CreateTemporary(data, true);
      src_file   := stdio.open(file_path, file_name, 'r');
      loop
         bytes := stdio.f_read(src_file, buff, 2000);
         if bytes > 0 then
            dbms_lob.writeappend(data, bytes, buff);
         else
            exit;
         end if;
      end loop;
      
      stdio.close(src_file);

      begin_attachment(conn, 'application/octet-stream', false, file_name, 'base64');
      msg_len   := dbms_lob.getlength(data);
      pos      := 1;
      offset   := MAX_BASE64_LINE_WIDTH;
   
      while pos < msg_len
      loop
         buff := dbms_lob.substr(data, offset, pos);
         utl_smtp.write_raw_data(conn, utl_encode.base64_encode(buff));
         utl_smtp.write_data(conn, utl_tcp.CRLF);
         
         pos      := pos + offset;   
         offset   := least(MAX_BASE64_LINE_WIDTH, msg_len - offset);
      end loop;
   
      end_attachment(conn, true);
      dbms_lob.FreeTemporary(data);
   end if;

   -- Закроем сообщение
   end_mail(conn);
end;

dnk_dz
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеСр Дек 24, 2008 07:05    Ответить с цитатой
Полезность: Нет оценки
Глобальное описание:
Код:

/*
   author         Alexandr Trapezin
   created date   27/07/2005
   comment         Библиотека для работы с SMTP
   oracle         9.0.2 или выше
*/

   smtp_host   VARCHAR2(256); -- почтовый сервер
   smtp_port   PLS_INTEGER;   -- порт почтового сервера
   smtp_domain VARCHAR2(256); -- домен
   mail_charset   varchar2(256);   -- кодировка письма

   MAILER_ID   CONSTANT VARCHAR2(256) := 'Mailer by iBank';

   BOUNDARY        CONSTANT VARCHAR2(256) := '-----7D81B75CCC90D2974F7A1CBD';
   FIRST_BOUNDARY  CONSTANT VARCHAR2(256) := '--'||BOUNDARY||utl_tcp.CRLF;
   LAST_BOUNDARY   CONSTANT VARCHAR2(256) := '--'|| BOUNDARY||'--'||utl_tcp.CRLF;

   MULTIPART_MIME_TYPE CONSTANT VARCHAR2(256) := 'multipart/mixed; boundary="'||BOUNDARY ||'"';
   MAX_BASE64_LINE_WIDTH CONSTANT PLS_INTEGER   := 76 / 4 * 3;

   -- структура вложений
   type attach_type is record (
      file_path   varchar2(256),
      file_name   varchar2(256)
   );
   type attach_tbl is table of attach_type index by binary_integer;

   -- отправка текстового сообщения
   -- получатели разделяются знаками "," или ";"
   PROCEDURE mail(
      sender     IN VARCHAR2,   -- Отправитель
      recipients IN VARCHAR2,   -- получатели
      subject    IN VARCHAR2,   -- тема
      message    IN VARCHAR2,   -- сообщение
      mime_type  IN VARCHAR2 DEFAULT 'text/plain'
   );

   -- отправить письмо с вложением файла
   -- файл должен существовать на локальном диске сервера!
   procedure send_mail_with_attach(
      sender     IN VARCHAR2, -- отправитель
      recipients IN VARCHAR2,   -- получатели
      subject    IN VARCHAR2, -- тема сообщения
      message    IN VARCHAR2, -- тело сообщения
      file_path  IN VARCHAR2, -- путь к файлу
      file_name  IN VARCHAR2, -- имя файла
      mime_type  IN VARCHAR2 DEFAULT 'text/plain'
   );

   -- отправить письмо с вложенными файлами
   -- файлы должены существовать на локальном диске сервера!
   procedure send_mail_with_attachments(
      sender     IN VARCHAR2, -- отправитель
      recipients IN VARCHAR2,   -- получатели
      subject    IN VARCHAR2, -- тема сообщения
      message    IN VARCHAR2, -- тело сообщения
      files  IN attach_tbl, -- файлы для вложения
      mime_type  IN VARCHAR2 DEFAULT 'text/plain'
   );

     -- расширеная функция отправки сообщения
     -- функция возвращает соединение которое может использоваться для операция write_text() и write_mb_text()
     -- соединение должно явно закрываться операцией end_mail()
   FUNCTION begin_mail(
      sender     IN VARCHAR2,
      recipients IN VARCHAR2,
      subject    IN VARCHAR2,
      mime_type  IN VARCHAR2    DEFAULT 'text/plain',
      priority   IN PLS_INTEGER DEFAULT NULL
   ) RETURN utl_smtp.connection;

   -- запись строки в тело сообщения в ASCII
   PROCEDURE write_text(
      conn    IN OUT NOCOPY utl_smtp.connection,   -- соединение
      message IN VARCHAR2   -- сообщение
   );

   -- запись строки в тело сообщения не в ASCII
   PROCEDURE write_mb_text(
      conn    IN OUT NOCOPY utl_smtp.connection,
      message IN            VARCHAR2
   );

     -- запись в тело сообщения бинарные данные
   PROCEDURE write_raw(
      conn    IN OUT NOCOPY utl_smtp.connection,
      message IN RAW
   );

  -- APIs to send email with attachments. Attachments are sent by sending
  -- emails in "multipart/mixed" MIME format. Specify that MIME format when
  -- beginning an email with begin_mail().

   -- отправка текстового вложения
   PROCEDURE attach_text(
      conn         IN OUT NOCOPY utl_smtp.connection,
      data         IN VARCHAR2,
      mime_type    IN VARCHAR2 DEFAULT 'text/plain',
      inline       IN BOOLEAN  DEFAULT TRUE,
      filename     IN VARCHAR2 DEFAULT NULL,
      last         IN BOOLEAN  DEFAULT FALSE
   );

   -- отправка бинарного вложения в формате Base-64
   PROCEDURE attach_base64(
      conn         IN OUT NOCOPY utl_smtp.connection,
      data         IN RAW,
      mime_type    IN VARCHAR2 DEFAULT 'application/octet',
      inline       IN BOOLEAN  DEFAULT TRUE,
      filename     IN VARCHAR2 DEFAULT NULL,
      last         IN BOOLEAN  DEFAULT FALSE
   );

   -- отправка вложения
   PROCEDURE begin_attachment(
      conn         IN OUT NOCOPY utl_smtp.connection,   -- соединение
      mime_type    IN VARCHAR2 DEFAULT 'text/plain',   -- тип сообщения
      inline       IN BOOLEAN  DEFAULT TRUE,
      filename     IN VARCHAR2 DEFAULT NULL,         -- имя файла
      transfer_enc IN VARCHAR2 DEFAULT NULL         -- кодиродить или нет
   );

   -- закрытие вложения
   PROCEDURE end_attachment(
      conn IN OUT NOCOPY utl_smtp.connection,
      last IN BOOLEAN DEFAULT FALSE
   );

   -- закрытие соединения
   PROCEDURE end_mail(
      conn IN OUT NOCOPY utl_smtp.connection
   );

   -- операции для работы с сесиями
   FUNCTION begin_session RETURN utl_smtp.connection;

   -- начало сесии
   PROCEDURE begin_mail_in_session(
      conn       IN OUT NOCOPY utl_smtp.connection,
      sender     IN VARCHAR2,
      recipients IN VARCHAR2,
      subject    IN VARCHAR2,
      mime_type  IN VARCHAR2  DEFAULT 'text/plain',
      priority   IN PLS_INTEGER DEFAULT NULL
   );

   -- закрытие сесии
   PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection);

   -- окончание сессии
   PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection);


   -- отправка сообщения
   -- получатели разделяются знаками "," или ";"
   procedure send_mail(
      sender         in varchar2(2000),      -- отправитель
      recipients      in varchar2(32000),      -- получатели
      subject         in varchar2(2000),      -- тема
      msg            in clob,                  -- сообщение
      file_path      in varchar2(256),       -- путь к файлу для отправки
      file_name      in varchar2(256)         -- имя файла для отправки
   );

timochev
Эксперт


Вступление в Клуб: 02.07.2007
СообщениеПн Фев 02, 2009 14:27    Ответить с цитатой
Полезность: Нет оценки
А кто-нибудь пользовался дистрибутивной библиотекой RUNTIME.SMTP_MAIL? Она работоспособна? Есть ли нарекания?
ranov
Участник


Вступление в Клуб: 24.06.2008
СообщениеСр Фев 11, 2009 09:43    Ответить с цитатой
Полезность: Нет оценки
timochev пишет:
А кто-нибудь пользовался дистрибутивной библиотекой RUNTIME.SMTP_MAIL? Она работоспособна? Есть ли нарекания?

Да. работает отлично. нужно исправить только в нескольких местах (для нашего сервера).
timochev
Эксперт


Вступление в Клуб: 02.07.2007
СообщениеЧт Авг 25, 2011 09:22    Ответить с цитатой
Полезность: 2
Нашли багу в процедуре send_mail. При размере LOB равном (k * MAX_BASE64_LINE_WIDTH + 1) теряется последний байт.
Для исправления надо сделать нестрогое неравенство в условии
Код:
while pos < msg_len

В результате получается так:
Код:
-- отправка сообщения
-- получатели разделяются знаками "," или ";"
procedure send_mail(
      sender         in varchar2(2000),      -- отправитель
      recipients      in varchar2(32000),      -- получатели
      subject         in varchar2(2000),      -- тема
      msg            in clob,                  -- сообщение
      file_path      in varchar2(256),       -- путь к файлу для отправки
      file_name      in varchar2(256)         -- имя файла для отправки
) is
   conn            utl_smtp.connection;
   msg_len         number;
   pos            number                   := 1;
   bytes_o_data   constant number          := 32767;
   offset         number                   := bytes_o_data;
   first_loop      boolean                  := true;
   attach_html      boolean                  := false;
   str            varchar2(32767);
   data            blob;
   src_file         number;
   buff            raw(2000);
   bytes            number;
begin
   conn      :=  begin_mail(sender, recipients, subject, MULTIPART_MIME_TYPE||' charset="windows-1251"');
   msg_len   := dbms_lob.getlength(msg);
   
   if msg_len > 0 then
      begin_attachment(conn,  'text/html; charset="windows-1251"', true, null);
      
      while pos < msg_len
      loop
         str := dbms_lob.substr(msg, offset, pos);
         if first_loop then
            first_loop := false;
            if instr(lower(str), '<html>') = 0 then
               -- Если простой текст, то добавим заголовки html
               attach_html := true;
               write_text(conn, '<html>');
               write_text(conn, '<head>');
               write_text(conn, '<title>');
               write_text(conn, subject);
               write_text(conn, '</title>');
               write_text(conn, '</head>');
               write_text(conn, '<body>');
            end if;
         end if;
         write_text(conn, str);
         pos      := pos + offset;
         offset   := least(bytes_o_data, msg_len - offset);
      end loop;
      if attach_html then
         write_text(conn, '</body>');
         write_text(conn, '</html>');
      end if;
      end_attachment(conn, false);   
   end if;


   if file_name is not null then      
      dbms_lob.CreateTemporary(data, true);
      src_file   := stdio.open(file_path, file_name, 'r');
      loop
         bytes := stdio.f_read(src_file, buff, 2000);
         if bytes > 0 then
            dbms_lob.writeappend(data, bytes, buff);
         else
            exit;
         end if;
      end loop;
      
      stdio.close(src_file);

      begin_attachment(conn, 'application/octet-stream', false, file_name, 'base64');
      msg_len   := dbms_lob.getlength(data);
      pos      := 1;
      offset   := MAX_BASE64_LINE_WIDTH;
   
      while pos <= msg_len
      loop
         buff := dbms_lob.substr(data, offset, pos);
         utl_smtp.write_raw_data(conn, utl_encode.base64_encode(buff));
         utl_smtp.write_data(conn, utl_tcp.CRLF);
         
         pos      := pos + offset;   
         offset   := least(MAX_BASE64_LINE_WIDTH, msg_len - offset);
      end loop;
   
      end_attachment(conn, true);
      dbms_lob.FreeTemporary(data);
   end if;

   -- Закроем сообщение
   end_mail(conn);
end;

Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Справочник PL/PLUS: Функции, примеры, приёмы Часовой пояс: GMT + 3
На страницу Пред.  1, 2, 3
Страница 3 из 3

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru