четверг, 23 августа 2012 г.

MS SQL 2008: Client IP address on shared hosting


Task:
get IP-address of the client (IP-address of client connection)
(for example to write to the log address of the computer you are using to connect)


Surroundings and limitations:
MS SQL 2008 database is on a hosting without admin rights.
There are no rights to execute dm_exec_connections.

Solution
(key line highlighted)

select
   CONNECTIONPROPERTY('net_transport') AS net_transport,
   CONNECTIONPROPERTY('protocol_type') AS protocol_type,
   CONNECTIONPROPERTY('auth_scheme') AS auth_scheme,
   CONNECTIONPROPERTY('local_net_address') AS local_net_address,
   CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
   CONNECTIONPROPERTY('client_net_address') AS client_net_address 

Links

MSDN help

MS SQL 2008 IP адрес клиента

Задача: 
получить IP-адрес клиента (IP-дарес клиентского соединения)
(например для того чтобы записывать в лог адрес компьютера с которого производилось подключение)


Окружение и ограничения: 
база MS SQL 2008 на хостинге, прав администартора нет. Прав на процедуру dm_exec_connections нет.

Решение
(ключевую строчку выделил)


 select
   CONNECTIONPROPERTY('net_transport') AS net_transport,
   CONNECTIONPROPERTY('protocol_type') AS protocol_type,
   CONNECTIONPROPERTY('auth_scheme') AS auth_scheme,
   CONNECTIONPROPERTY('local_net_address') AS local_net_address,
   CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
   CONNECTIONPROPERTY('client_net_address') AS client_net_address 


Ссылки
Оригинал на английском
http://weblogs.sqlteam.com/peterl/archive/2010/03/20/Get-client-IP-address.aspx

Помощь в MSDN по свойству CONNECTIONPROPERTY
http://msdn.microsoft.com/en-us/library/bb895240.aspx

вторник, 21 августа 2012 г.

Bitrix - Дополнительные поля в почтовом уведомлении о новом заказе

Задача: добавить поля "комментарий киента к заказу", "телефон", "название службы доставки", "название способа оплаты", "полный адрес клиента" в шаблон письма-уведомления о новом заказе

Идея решения:
1. Добавляем новые поля в шаблон почтового события SALE_NEW_ORDER.
Поля добавляем в текст шаблона в виде
#<имя поля>#

2. Добавляем в систему обработчик события "перед отправкой почтового уведомления о новом заказе".
3. В обработчике события заполняем добавленные в шаблон поля

Решение
Шаг 1. Шаблон SALE_NEW_ORDER

В шаблон добавил такой текст

...
Контактный телефон: #PHONE#
Комментарий:
#ORDER_DESCRIPTION#
Служба доставки: #DELIVERY_NAME#
Способ оплаты: #PAY_SYSTEM_NAME#
Адрес доставки: #FULL_ADDRESS#
...

Шаги 2 и 3. Код

в /bitrix/php_interface/init.php

вписал такой код
Код
//-- Добавление обработчика события

AddEventHandler("sale", "OnOrderNewSendEmail", "bxModifySaleMails");

//-- Собственно обработчик события

function bxModifySaleMails($orderID, &$eventName, &$arFields)
{
  $arOrder = CSaleOrder::GetByID($orderID);
  
  //-- получаем телефоны и адрес
  $order_props = CSaleOrderPropsValue::GetOrderProps($orderID);
  $phone="";
  $index = ""; 
  $country_name = "";
  $city_name = "";  
  $address = "";
  while ($arProps = $order_props->Fetch())
  {
    if ($arProps["CODE"] == "PHONE")
    {
       $phone = htmlspecialchars($arProps["VALUE"]);
    }
    if ($arProps["CODE"] == "LOCATION")
    {
        $arLocs = CSaleLocation::GetByID($arProps["VALUE"]);
        $country_name =  $arLocs["COUNTRY_NAME_ORIG"];
        $city_name = $arLocs["CITY_NAME_ORIG"];
    }

    if ($arProps["CODE"] == "INDEX")
    {
      $index = $arProps["VALUE"];   
    }

    if ($arProps["CODE"] == "ADDRESS")
    {
      $address = $arProps["VALUE"];
    }
  }

  $full_address = $index.", ".$country_name."-".$city_name.", ".$address;

  //-- получаем название службы доставки
  $arDeliv = CSaleDelivery::GetByID($arOrder["DELIVERY_ID"]);
  $delivery_name = "";
  if ($arDeliv)
  {
    $delivery_name = $arDeliv["NAME"];
  }

  //-- получаем название платежной системы   
  $arPaySystem = CSalePaySystem::GetByID($arOrder["PAY_SYSTEM_ID"]);
  $pay_system_name = "";
  if ($arPaySystem)
  {
    $pay_system_name = $arPaySystem["NAME"];
  }

  //-- добавляем новые поля в массив результатов
  $arFields["ORDER_DESCRIPTION"] = $arOrder["USER_DESCRIPTION"]; 
  $arFields["PHONE"] =  $phone;
  $arFields["DELIVERY_NAME"] =  $delivery_name;
  $arFields["PAY_SYSTEM_NAME"] =  $pay_system_name;
  $arFields["FULL_ADDRESS"] = $full_address;   
}



Полезные ссылки

Прототип кода взял из комментария к статье "Артикул в уведомлении о заказе" Спасибо автору
http://dev.1c-bitrix.ru/community/webdev/user/46046/blog/articles-in-the-notification-of-the-order/
События интернет-магазина
Тут помог раздел "События связанные с отправкой почтовых шаблонов"
http://dev.1c-bitrix.ru/api_help/sale/sale_events.php
Курс разработчика, раздел "Обработка событий"
http://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=46&LESSON_ID=2222
Документация для разработчика, раздел "Обработка событий"
http://dev.1c-bitrix.ru/api_help/main/general/technology/events.php
Тема форума "Обработка событий"
http://dev.1c-bitrix.ru/community/forums/forum6/topic28942/

Delphi Indy 10 SSL and Encoding Issues


When sending mail through Indy components in Delphi 7 encountered periodically on different issues.
Variants of problems:


  • sending emails from machines that - there are Russian letters in the names
  • email using SSL
  • problems with encoding in the subject and body of the message


I didn't find common solution in internet - only scattered pieces.

All solutions brought here. May be it will be useful for someone (tested on russian charsets)

System configuration:

  • Delphi 7, 
  • Indy components version: 10.5.9.4797 (installed manually by article http://conferences.embarcadero.com/article/32160
    file: Indy10_4798.zip)
  • SSL Library: openssl-1.0.0d-i386-win32.zip
    from http://indy.fulgan.com/SSL/
    (files libeay32.dll and ssleay32.dll are copied to project output directory)

main procedure is - SendEmail
Main pieces of code are commented.

uses
...

IdCoderMIME , IdMessage, IdSMTP,
IdSSLOpenSSL , IdIOHandler, IdAttachmentFile, IdExplicitTLSClientServerBase, idCharSets, idText
...

type

  //-- helper stub-class for TidMessage.OnInitializeISO event  handling
  Tindystub = class(tobject)
  public
    procedure OnInitISO(var VHeaderEncoding: Char; var VCharSet: string);
  end;

procedure Tindystub.OnInitISO(var VHeaderEncoding: Char;
  var VCharSet: string);
begin
  VCharSet := IdCharsetNames[ idcs_UTF_8 ];
end;


procedure SendEmail(
    aSmtpServer: string;
    aSmtpPort: integer;
    aSmtpLogin: string;
    aSmtpPassword: string;
    aFromAddress: string;
    aFromName: string;
    aToAddress: string;
    aMessageSubject: string;
    aMessageText: string;
    aAttachmentFileFullName: string;
    aUseSSL: boolean = false
    );
var
  lMessage : TIDMessage;
  lSMTP    : TIdSMTP;
  attach   : TIdAttachmentFile;
  sslHandler: TIdSSLIOHandlerSocketOpenSSL;
  lindystub: Tindystub;
  idtTextPart: TIdText;
begin
  lMessage:= TIDMessage.Create(nil);
  lSmtp:= TIDSmtp.Create(nil);
  sslHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  lindystub:= Tindystub.Create();
  try
    lSMTP.AuthType:= satDefault;

    lSMTP.Host     := aSmtpServer;   //Хост
    lSMTP.Port     := aSmtpPort;     //Порт (25 - по умолчанию)

    lSMTP.Username := aSmtpLogin;
    lSMTP.Password := aSmtpPassword;

    //-- solving "non-english computer name" problem
    lSMTP.HeloName := 'tfo';

    //-- using SSL
    if (aUseSSL) then
    begin
      SSLHandler.Destination := aSmtpServer+':'+IntToStr(aSmtpPort);
      SSLHandler.Host := aSmtpServer;
      SSLHandler.Port := aSmtpPort;
      SSLHandler.DefaultPort := 0;
      SSLHandler.SSLOptions.Method := sslvSSLv23;
      SSLHandler.SSLOptions.Mode := sslmUnassigned;
      lSMTP.IOHandler := SSLHandler;
      lSMTP.UseTLS := utUseImplicitTLS;
    end;

    //-- subject encoding
    lMessage.OnInitializeISO := lindystub.OnInitISO;

    lMessage.Subject      := aMessageSubject;
    lMessage.From.Address := aFromAddress;
    lMessage.From.Name    := aFromName;
    lMessage.Recipients.EMailAddresses:= aToAddress;

    //-- message body encoding
    idtTextPart := TIdText.Create(lMessage.MessageParts, nil);
    idtTextPart.ContentType := 'text/plain';
    idtTextPart.CharSet := 'Windows-1251';

    idtTextPart.Body.Text:= aMessageText;

    //-- work with attached files
    if (aAttachmentFileFullName <> '') then
    begin
      attach:=TIdAttachmentFile.Create(lMessage.MessageParts, aAttachmentFileFullName); //Вложение
    end;

    //-- sending email
    lSMTP.Connect;
    try
      lSMTP.Send(lMessage);
    finally
      lSMTP.Disconnect;
    end;

  finally
    sslHandler.Free;
    lMessage.Free;
    lSmtp.Free;
    lindystub.Free;
  end;
end;

Delphi Indy 10 SMTP Кодировки и SSL Решение все в одном


При отправке писем через SMTP компоненты Indy в Delphi 7 наталкивался периодически на разные проблемы.
Варианты проблем:

  • отправка писем от машин, у которых - есть русские буквы в названиях
  • отправка писем через SSL
  • проблемы с кодировками в теме и теле письма

В интернете общего решения не находил - только разрозненные части.

Все решения свел здесь. может кому-то пригодится

Конфигурация системы:

  • Delphi 7, 
  • Версия компонентов Indy:10.5.9.4797 (переустанавливал вручную по статье http://conferences.embarcadero.com/article/32160  файл: Indy10_4798.zip)
  • ssl - библиотеки: openssl-1.0.0d-i386-win32.zip
    брал отсюда http://indy.fulgan.com/SSL/
    (в директорию с exe-файлом подложил libeay32.dll и ssleay32.dll)


Ключевая процедура в коде - SendEmail
Важные места подкомментировал.

uses
...

IdCoderMIME , IdMessage, IdSMTP,
IdSSLOpenSSL , IdIOHandler, IdAttachmentFile, IdExplicitTLSClientServerBase, idCharSets, idText
...

type

  //-- вспомогательный класс-заглушка для подвязки события компонента indy
  Tindystub = class(tobject)
  public
    procedure OnInitISO(var VHeaderEncoding: Char; var VCharSet: string);
  end;

procedure Tindystub.OnInitISO(var VHeaderEncoding: Char;
  var VCharSet: string);
begin
  VCharSet := IdCharsetNames[ idcs_UTF_8 ];
end;


procedure SendEmail(
    aSmtpServer: string;
    aSmtpPort: integer;
    aSmtpLogin: string;
    aSmtpPassword: string;
    aFromAddress: string;
    aFromName: string;
    aToAddress: string;
    aMessageSubject: string;
    aMessageText: string;
    aAttachmentFileFullName: string;
    aUseSSL: boolean = false
    );
var
  lMessage : TIDMessage;
  lSMTP    : TIdSMTP;
  attach   : TIdAttachmentFile;
  sslHandler: TIdSSLIOHandlerSocketOpenSSL;
  lindystub: Tindystub;
  idtTextPart: TIdText;
begin
  lMessage:= TIDMessage.Create(nil);
  lSmtp:= TIDSmtp.Create(nil);
  sslHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  lindystub:= Tindystub.Create();
  try
    lSMTP.AuthType:= satDefault;

    lSMTP.Host     := aSmtpServer;   //Хост
    lSMTP.Port     := aSmtpPort;     //Порт (25 - по умолчанию)

    lSMTP.Username := aSmtpLogin;
    lSMTP.Password := aSmtpPassword;

    //-- решаем проблему отправки писем, если у компьютера руссоке имя
    lSMTP.HeloName := 'tfo';

    //-- отправляем почту через SSL, если надо (пока тестировал только на ukr.net)
    if (aUseSSL) then
    begin
      SSLHandler.Destination := aSmtpServer+':'+IntToStr(aSmtpPort);
      SSLHandler.Host := aSmtpServer;
      SSLHandler.Port := aSmtpPort;
      SSLHandler.DefaultPort := 0;
      SSLHandler.SSLOptions.Method := sslvSSLv23;
      SSLHandler.SSLOptions.Mode := sslmUnassigned;
      lSMTP.IOHandler := SSLHandler;
      lSMTP.UseTLS := utUseImplicitTLS;
    end;

    //-- решаем вопрос кодировки темы письма
    lMessage.OnInitializeISO := lindystub.OnInitISO;

    lMessage.Subject      := aMessageSubject;
    lMessage.From.Address := aFromAddress;
    lMessage.From.Name    := aFromName;
    lMessage.Recipients.EMailAddresses:= aToAddress;

    //-- решаем вопрос кодировки тела письма
    idtTextPart := TIdText.Create(lMessage.MessageParts, nil);
    idtTextPart.ContentType := 'text/plain';
    idtTextPart.CharSet := 'Windows-1251';

    idtTextPart.Body.Text:= aMessageText;

    //-- работа со вложенными файлами
    if (aAttachmentFileFullName <> '') then
    begin
      attach:=TIdAttachmentFile.Create(lMessage.MessageParts, aAttachmentFileFullName); //Вложение
    end;

    //-- собственно отправка
    lSMTP.Connect;
    try
      lSMTP.Send(lMessage);
    finally
      lSMTP.Disconnect;
    end;

  finally
    sslHandler.Free;
    lMessage.Free;
    lSmtp.Free;
    lindystub.Free;
  end;
end;


Вопросы/пожелания/предложения оставляйте в комментариях

см. также

Обработка почты через POP3 компоненты Indy10 в Delphi 7
http://dev-doc.blogspot.com/2013/02/delphi-indy-10-pop3.html

EMAIL MESSAGES FROM DELPHI. USING INDY TO SEND E-MAILS
https://community.embarcadero.com/article/technical-articles/162-programming/5913-email-messages-from-delphi-using-indy-to-send-emails
---------------------------------
UPD
Если хотите отправить почту через ukr.net
проверьте чтобы были включен параметр "POP3 и SMTP" согласно статье
http://www.qdpro.com.ua/node/17758
(если не сделать, будет выскакивать ошибка SYSERR 417)