понедельник, 17 мая 2021 г.

Проблема с IP*Works

Заметил, что при скачивании вложенных файлов из письма (которое в моем сервисе реализовано через Ip*Works, версия 20.0.7447) иногда имя вложенного файла определяется неверно. Каждый раз как "xls". Если смотреть содержимое письма в Outlooke, то там указано другое имя вложения.
Исследование под дебагером подтвердило, что проблема в стороннем софте, т.е. в компоненте Ip*Works
Далее я экспортировал письмо из Аутлука в файл и открыл его в HEX-редакторе.
В текстовой части (справа) мне удалось найти заголовки вложения. Они были закодированы по BASE-64. Когда я их раскодировал, оказалось, что это и было необходимое мне имя вложения.
Написав в тех. поддержку, я стал обдумывать как обойти эту проблему. Первая мысль была самостоятельно парсить заголовки и вместо "name" брать "filename". Но тут подоспел ответ от тех. поддержки Ip*Works, предлагали добавить магическую строчку ".Config('UseAttachmentNameParam=false');"

Таким образом, демонстрационный пример для скачивания вложений в письме с помощью Ip*Works выглядит так:

program Demo;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  ipwCore,
  ipwIMAP,
  ipwtypes,
  System.SysUtils;


var
  ImapHandle:  TipwIMAP;

procedure InitImap();
begin
  ImapHandle.MailServer := 
  ImapHandle.MailPort   := 
  ImapHandle.User       := 
  ImapHandle.Password   := 
  ImapHandle.SSLEnabled := False;
  ImapHandle.AutoDecodeParts := True;
  ImapHandle.Config('UseAttachmentNameParam=false');
end;

begin
  ImapHandle := TipwIMAP.Create(nil);
  try
    try
      InitImap();
      ImapHandle.Connect();
      ImapHandle.Mailbox := 'INBOX';
      ImapHandle.SelectMailbox();

      for var I := ImapHandle.MessageCount - 1 downto ImapHandle.MessageCount - 1 do
      begin
        ImapHandle.MessageSet := i.ToString();
        ImapHandle.FetchMessageInfo();

        WriteLn('Id         : ' + ImapHandle.MessageId);
        WriteLn('From       : ' + ImapHandle.MessageFrom);
        WriteLn('Subject    : ' + ImapHandle.MessageSubject);
        WriteLn('Flags      : ' + ImapHandle.MessageFlags);
        WriteLn('ContentType: ' + ImapHandle.MessageContentType);
        WriteLn('Size       : ' + ImapHandle.MessageSize.ToString);
        WriteLn('');

        for var j := 0 to ImapHandle.MessageParts.Count - 1 do
        begin
          if ImapHandle.MessageParts[j].Filename <> '' then
          begin
            WriteLn('    Id          : ' + ImapHandle.MessageParts[j].Id);
            WriteLn('    ContentId   : ' + ImapHandle.MessageParts[j].ContentId);
            WriteLn('    Filename    : ' + ImapHandle.MessageParts[j].Filename);
            WriteLn('    ContentType : ' + ImapHandle.MessageParts[j].ContentType);
            WriteLn('    Size        : ' + ImapHandle.MessageParts[j].Size.ToString);
            WriteLn('');
          end
        end
      end;

    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;

  finally
    FreeAndNil(ImapHandle);
  end;

  Write(#13#10 + 'press any key to continue...');
  ReadLn;
end.

среда, 12 мая 2021 г.

Сборка OpenCV

0) Проблема: требуется установить opencv 2.4.13 и настроить для работы в VS 2017 

(в дистрибутиве OpenCV собранные бинарники для VC11, VC12 не прилинкуются в новой студии, значит надо собирать из исходников)

1) Качаем последний cmake с сайта https://cmake.org/download/

https://github.com/Kitware/CMake/releases/download/v3.18.0/cmake-3.18.0-win64-x64.msi

2) Устанавливаем cmake в каталог студии (у меня там стоял предыдущий cmake версии 3.12.0, поставленный инсталлятором),

0 просто заменяя папку CMake (если такой папки нет, то можно ставить куда угодно)

C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake

3) Качаем opencv-2.4.13.exe и распаковываем в C:/opencv-2-4-13 

4) Запускаем "Командная строка для разработчика VS 2017" (если CMake был поставлен в другую папку, то надо в Path прописать до неё путь)

5) Набираем 

> cmake --version

Должно выдать 

> cmake version 3.18.0

6) Проверяем генераторы, набираем

> cmake -G

Должно выдать полный список генераторов. Поскольку у нас VS 2017 и Win32, то там это должно быть

(за подробностями в документацию https://cmake.org/cmake/help/v3.18/generator/Visual%20Studio%2015%202017.html)

7) Переходим в каталог C:/opencv2/sources, там должен быть файл CMakeLists.txt, набираем (если хотим собрать Win32 для opencv)

> cmake . -G "Visual Studio 15 2017" -A Win32

8) В студии открыть OpenCV.sln, пересобрать проект ALL_BUILD (Win32 Debug)

9) Создать 

C:\opencv-2-4-13\build\Debug\Win32\bin

C:\opencv-2-4-13\build\Debug\Win32\lib

C:\opencv-2-4-13\build\include

10) Скопировать в эти каталоги содержимое

C:\opencv-2-4-13\build\Debug\Win32\bin:

C:\opencv-2-4-13\sources\bin\Debug

C:\opencv-2-4-13\build\Debug\Win32\lib:

C:\opencv-2-4-13\sources\lib\Debug

C:\opencv-2-4-13\build\include:

C:\opencv-2-4-13\sources\include

C:\opencv-2-4-13\sources\modules\calib3d\include

C:\opencv-2-4-13\sources\modules\contrib\include

C:\opencv-2-4-13\sources\modules\photo\include

(Если прикомпиляции не будут найдены ещё какие-то файлы .h или .hpp надо их найти и прописать сюда путь до них)

11) Создать пустой проект С++, добавить новый файл main.cpp

12) Внутри файла:

#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
	namedWindow("Win");
	waitKey(0);
	return 0;
}

13) Правой кнопкой мыши по проекту

Проект -> Свойства -> Каталоги VC++

Каталоги исполняемых файлов -> C:\opencv-2-4-13\build\Debug\Win32\bin

Включаемые каталоги -> C:\opencv-2-4-13\build\include

Каталоги библиотек -> C:\opencv-2-4-13\build\Debug\Win32\lib

Компоновщик

Общие -> Дополнительные каталоги библиотек -> C:\opencv-2-4-13\build\Debug\Win32\lib

Ввод -> Дополнительные зависимости -> указываем всё, что есть в /lib, а именно:

opencv_calib3d2413d.lib

opencv_contrib2413d.lib

opencv_core2413d.lib

opencv_features2d2413d.lib

opencv_flann2413d.lib

opencv_gpu2413d.lib

opencv_haartraining_engined.lib

opencv_highgui2413d.lib

opencv_imgproc2413d.lib

opencv_legacy2413d.lib

opencv_ml2413d.lib

opencv_nonfree2413d.lib

opencv_objdetect2413d.lib

opencv_ocl2413d.lib

opencv_photo2413d.lib

opencv_stitching2413d.lib

opencv_superres2413d.lib

opencv_ts2413d.lib

opencv_video2413d.lib

opencv_videostab2413d.lib

События сборки -> События после сборки -> Командная строка -> xcopy /y /d "C:\opencv-2-4-

13\build\Debug\Win32\bin\*.dll" "$(OutDir)"

14) Проверка

#include <opencv2\opencv.hpp>
using namespace cv;
int main()

using namespace cv;
using namespace std;

int main()
{
	namedWindow("Win");
	waitKey(0);
	// задаём высоту и ширину картинки
	int height = 620;
	int width = 440;
	// задаём точку для вывода текста
	CvPoint pt = cvPoint(height / 4, width / 2);
	// Создаёи 8-битную, 3-канальную картинку
	IplImage* hw = cvCreateImage(cvSize(height, width), 8, 3);
	// заливаем картинку чёрным цветом
	cvSet(hw, cvScalar(0, 0, 0));
	// инициализация шрифта
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0, 0, 1, CV_AA);
	// используя шрифт выводим на картинку текст
	cvPutText(hw, "OpenCV Step By Step", pt, &font, CV_RGB(150, 0, 150));
	// создаём окошко
	cvNamedWindow("Hello World", 0);
	// показываем картинку в созданном окне
	cvShowImage("Hello World", hw);
	// ждём нажатия клавиши
	cvWaitKey(0);
	// освобождаем ресурсы
	cvReleaseImage(&hw);
	cvDestroyWindow("Hello World");
	//cout << "\r\npress any key to continue...";
	//cin.get();
	return 0;
}