Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ilya_er
Member

Откуда: Москва
Сообщений: 206
Проблема в следующем: есть процедура, она формировала отчет-напоминание и отсылала по почте. Использовала xp_smtp_sendmail (у меня SQL2000). Отчет выгружался с помощью bcp в файл и процедура брала текст из файла. Тело отчета - в html. xp_smtp_sendmail. Проблем не было.

Через некоторое время на smtp-сервере установили запрет на отсылку без авторизации. Пришлось переползти на CDO.Message. Отсылка заработала, но возникла проблема:

Воспроизвести на серверной стороне загрузку тела письма из файла не удалось. Стал вызывать процедуру через exec + конкатенация строк (как тут).
Текст процедуры, отпраляющей почту :
IF EXISTS (SELECT name 
	   FROM   sysobjects 
	   WHERE  name = N'cp_send_cdosysmail'
	   AND 	  type = 'P')
    DROP PROCEDURE cp_send_cdosysmail
GO

/*********************************************************************
См. ссылку CDOSYS objects по следующему адресу MSDN Web site:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_messaging.asp
***********************************************************************/

CREATE PROCEDURE dbo.cp_send_cdosysmail
@SMTPServerName VARCHAR(100), 
@username varchar(100),
@password varchar(100),
@Charset varchar(10)='koi8-r', --'unicode', 

@To VARCHAR(100),
@From VARCHAR(100),
@Subject NVARCHAR(100)=" ",
@Body ntext=" ",
@CC VARCHAR(100)=NULL,
@BCC VARCHAR(100)=NULL
AS
SET NOCOUNT ON
DECLARE @iMsg INTEGER, @hr INTEGER, @source VARCHAR(255), @description VARCHAR(500), @output VARCHAR(1000),
  @iFile integer, @authtype int, @res int

 set @authtype = 1 -- clear text; OAbASIC
--SET @SMTPServerName='192.168.1.3' -- Указываем имя или IP-адрес SMTP-сервера, например, 'localhost'

 if @Charset is null
  set  @Charset='koi8-r'
  --set @Charset='unicode'

EXEC @hr=sp_OACreate 'CDO.Message', @iMsg OUT
-- Конфигурируем удалённый SMTP-сервер:
-- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_schema_configuration_sendusing.asp
-- 1=значит отсылка сообщения будет осуществляться через локальный SMTP-сервер
-- 2=значит отсылка сообщения будет осуществляться через SMTP-сервер домена
EXEC @hr=sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value','2'

EXEC @hr=sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value', @SMTPServerName
EXEC @hr=sp_OAMethod @iMsg, 'Configuration.Fields.Update', null -- Устанавливаем конфигурацию message-объекта

EXEC @hr=sp_OASetProperty @iMsg, 'To', @To
EXEC @hr=sp_OASetProperty @iMsg, 'From', @From
EXEC @hr=sp_OASetProperty @iMsg, 'CC', @CC
EXEC @hr=sp_OASetProperty @iMsg, 'BCC', @BCC
EXEC @hr=sp_OASetProperty @iMsg, 'Subject', @Subject

-- !!!! далее - война с кодировкой
EXEC @hr = sp_OASetProperty @iMsg, 'Configuration.fields("urn:schemas:mailheader:content-language").Value',  @Charset

EXEC @hr=sp_OASetProperty @iMsg, 'HTMLBodyPart.Charset', @Charset
EXEC @hr=sp_OASetProperty @iMsg, 'HTMLBodyPart.CODEPAGE', 20866




if not (@username is null) and not (@password is null) 
begin
  EXEC @hr=sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate").Value', @authtype -- тип аутентификации
  EXEC @hr=sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusername").Value', @username  -- имя пользователя
  EXEC @hr=sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendpassword").Value', @password  -- пароль
  EXEC @hr=sp_OASetProperty @iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpaccountname").Value', @username  -- имя пользователя

end

-- If you are using HTML e-mail, use 'HTMLBody' instead of 'TextBody'.
EXEC @hr=sp_OASetProperty @iMsg, 'HTMLBody', @Body
EXEC @hr=sp_OAMethod @iMsg, 'Send', NULL


-- Если указан НЕкорректный e-mail адрес, то будет возвращён код 2147220977.
-- Если указан НЕкорректное имя MAIL Server-а, то будет возвращён код -2147220973
/*
IF @hr <>0
SELECT @hr
BEGIN
*/
EXEC @hr = sp_OAGetErrorInfo NULL, @source OUT, @description OUT
set @res = @hr
/*
IF @hr=0
BEGIN
SELECT @output = ' Источник: ' + @source
PRINT @output
SELECT @output = ' Описание: ' + @description
PRINT @output
END
ELSE
BEGIN
PRINT ' p_OAGetErrorInfo ошибка!'
print @hr
END
--END
*/

EXEC @hr = sp_OADestroy @iMsg
RETURN @res
go


В заголовке html кодировка так же указывается.
Кодировка устанавливается (комментарий, помеченный -- !!!! в коде). Т.к. она одна, case для определения кодовой страницы писать я не стал.
Проблема в следующем : физически письмо приходит в кодировке koi-8. При вызове формирующей процедуры из QA все работает. При вызове процедуры через job c вероятностью примерно 40% приходят знаки вопроса, в остальных случаях письма приходят корректные.

В качестве клиента используется в компании The Bat ! и менять это не хотелось бы.

Т.к. штатный запуск - раз в сутки, хотелось бы это побороть...

Пример с отдельным OLE-объектом для зачитывания тела письма из файла на vbscript я нашел, но - непонятно, можно ли получить ответ от одной sp_OASetProperty и скормить его другой... Хотя - тогда тело было бы в unicode, как bcp формирует, и проблема была бы решена.
4 дек 06, 14:02    [3487459]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ilya_er
Member

Откуда: Москва
Сообщений: 206
Главное - если бы всегда приходили знаки вопроса, я бы понял - неправильно настроен объект, а тут - то приходит корректный текст, то - некорректный... и именно из джоба...
4 дек 06, 18:23    [3489506]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ilya_er
Member

Откуда: Москва
Сообщений: 206
В общем, как всегда. Стоило весь текст, включая текст динамического sql перевести в nvarchar/ntext - и все заработало. Кстати, оказалось, что exec() нормально переваривает nvarchar.
7 дек 06, 13:09    [3504078]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ilya_er
Member

Откуда: Москва
Сообщений: 206
Поторопился... все равно, как оказалось, через раз знаки вопроса приходят.Заметил, что в "хороших" письмах в служебной информации сабжект письма выглядит так :
Subject: =?koi8-r?B?7sXPwsjPxMnNz9PU2CDBy9TVwczJ2sHDyckg0NLBytMtzMnT1M/X?=

а в плохих - так :
Subject: ????????????? ???????????? ?????-??????

То есть, он через раз понимает, что кодировка ?koi8-r?, хотя сообщение формирует одна и та же процедура.
Тест проводился установкой отправки письма через job раз в минуту в течение 10 минут.

Неужели ни у кого никаких мыслей нет ?
7 дек 06, 13:43    [3504416]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ilya_er
Member

Откуда: Москва
Сообщений: 206
Ладно, раз все молчат, другой вопрос - из какого файла MSSQL 2000 берет класс CDO.Message ?

Следы на msdn.com ведут к cdo.dll, библиотеки такой у меня на машине нет, а CDO.Message работает.

И, для верности, @@version
-- тестовый сервер
Microsoft SQL Server  2000 - 8.00.2039 (Intel X86) 
	May  3 2005 23:18:38 
	Copyright (c) 1988-2003 Microsoft Corporation
	Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 2)

-- рабочий сервер
Microsoft SQL Server  2000 - 8.00.760 (Intel X86) 
	Dec 17 2002 14:22:05 
	Copyright (c) 1988-2003 Microsoft Corporation
	Standard Edition on Windows NT 5.0 (Build 2195: Service Pack 4)


На тестовом стоит SP4. На рабочем - SP3, кроме моей системы там стоит еще сторонняя, поэтому я бы с радостью не стал ставить туда SP4, если это возможно. Не уверен, как эта система себя поведет.
15 дек 06, 12:59    [3541497]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ilya_er
Member

Откуда: Москва
Сообщений: 206
Нашел пример задания параметров, выставил
'Configuration.Fields.Update'
в нескольких местах... попытался создавать явно части сообщения... все равно не работает..... максимальный результат - 70%... Ну хоть у кого-нибудь мысли есть ?
15 дек 06, 16:05    [3543140]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
Ёжик`
Member

Откуда:
Сообщений: 5992
cdosys.dll
15 дек 06, 20:49    [3544693]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4257
ilya_er
Ладно, раз все молчат, другой вопрос - из какого файла MSSQL 2000 берет класс CDO.Message ?

Следы на msdn.com ведут к cdo.dll, библиотеки такой у меня на машине нет, а CDO.Message работает.



быть такого не может. CDO - это API аутлука для работы с Exchange. То есть у вас должен быть настроен профайл, откуда все установки (в том числе и кодировки) по умолчанию и должны браться.
15 дек 06, 21:26    [3544765]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3146
Были аналогичные проблемы. Пришлось написать standalone EXE на VB6, который и занимается собственно отправкой. В нем это выглядит примерно так (вкратце):
Private Sub SendMail()
' CDO Objects
Dim iBp As CDO.IBodyPart
Dim Msg As CDO.Message
' Init root CDO object
Set Msg = New CDO.Message
With Msg
  .AutoGenerateTextBody = False
  .From = "from"
  .To = "to"
End With
' !!! Get correct interface from this object
Set iBp = Msg
' !!! Set some content-related properties
With iBp
  .ContentMediaType = cdoTextHTML
  .ContentTransferEncoding = cdo8bit
  .Charset = cdoUTF_8
End With
' Set sending properties
With Msg.Configuration.Fields
  .Item(cdoSendUsingMethod) = cdoSendUsingPort
  .Item(cdoSMTPServer) = "smtp.server"
  .Item(cdoSMTPConnectionTimeout) = 60
  .Item(cdoSMTPAuthenticate) = cdoBasic
  .Item(cdoSendUserName) = "name"
  .Item(cdoSendPassword) = "password"
  .Update
End With
Msg.HTMLBody = ... ' Some HTML code
' Get subject from HTML title
Msg.Fields(cdoSubject) = Doc.Title
Msg.Fields(cdoXMailer) = App.Title
Msg.Fields.Update
' Send!
Msg.Send
End Sub
Прикол в том, что нужно от переменной Msg взять интерфейс IBodyPart и манипулировать уже с его свойствами. Как это сделать в VBScript и можно ли в нем такое сделать вообще - не знаю, вроде как нет (из-за отсутствия типизации). Так или иначе, но ключевым, кажется, оказалось свойство IBodyPart.Charset.
15 дек 06, 21:42    [3544800]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3146
Lepsik
CDO - это API аутлука для работы с Exchange. То есть у вас должен быть настроен профайл, откуда все установки (в том числе и кодировки) по умолчанию и должны браться.

Вы путаете CDO и MAPI. В последнем случае в системе действительно должен быть установлен почтовый клиент и настроена учетка почты.
Что же касается CDO, то эта библиотека входит в состав винды, начиная с W2K и ничьим API, насколько я помню, не является. В составе MS Exchange идет специализированная версия этой библы, да, но разница между этими версиями не имеет никакого отношения к данному вопросу.
15 дек 06, 21:47    [3544812]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
-Iriska-
Member

Откуда: Kiev
Сообщений: 2
ilya_er,

нужно задать кодировку в свойстве объекта CDO.Mesage:

.BodyPart.Charset = "windows-1251"
17 авг 12, 23:04    [13029451]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6719
-Iriska-, уже почти 6 лет прошло. Думаю им уже это не надо. =)

Блин, а в мире столько готовых стандартных OpenSource утилит аля SendMail, что городить огород и тонны и месиво кода просто преступление.
18 авг 12, 02:30    [13029831]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
ЗууеВ
Guest
Мне помогло. Спасибо 8-)
24 апр 14, 04:53    [15926477]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
dolly_ev
Member

Откуда: Чита
Сообщений: 29
Mnior
-Iriska-, уже почти 6 лет прошло. Думаю им уже это не надо. =)

Прошло еще 2 года и мне тоже помогло :-)) Спасибо!
6 июл 14, 12:06    [16265140]     Ответить | Цитировать Сообщить модератору
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
Алекс2014
Member

Откуда:
Сообщений: 1
Помогли такие строки
-- Установка кодировки для текста
--EXEC @hr = sp_OAGetProperty @iMsg, 'TextBodyPart', @BodyPart out
--EXEC @hr = sp_OASetProperty @BodyPart, 'Charset', 'windows-1251'

-- Установка кодировки для html
---- для html body
EXEC @hr = sp_OAGetProperty @iMsg, 'HTMLBodyPart', @BodyPart out
EXEC @hr = sp_OASetProperty @BodyPart, 'Charset', 'windows-1251'
---- для html header
EXEC @hr = sp_OAGetProperty @iMsg, 'BodyPart', @BodyPart out
EXEC @hr = sp_OASetProperty @BodyPart, 'Charset', 'windows-1251'
9 июн 15, 10:50    [17748290]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: CDO.Message - настроить кодировку либо тело письма брать из файла  [new]
GigaWatt
Member

Откуда:
Сообщений: 1
Класс! Прошло ещё 4 года, а тема не перестаёт помогать!
27 фев 18, 12:12    [21221358]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить