Архив метки: python

Python 3: Сохранение вложения из письма по протоколу IMAP

Задача: посмотреть в почтовом ящике письмо. Если в нем есть вложение — сохранить его в папку. Письмо удалить.

Решение 1 (листаем по одному письму):

#!/usr/bin/env python3
#encoding: UTF-8
import sys
import imaplib
import email
import os

server = "mail.esrgsergser.ru"
port = "143"
login = "strgsere@sgergsergse.ru"
password = "werferfe"
putdir="/home/pavel/";

ver="1.0";
copyleft="(c) 2018 by Pavel Gribov http://грибовы.рф";
comment="Сей чудный скрипт смотрит почту по imap протоколу, сохраняет вложения в заданную папку, удаляет письмо с сервера";

# История изменений

##

print (ver);
print (copyleft);
print (comment);

if len(sys.argv)==1:
    print ("Возможные параметры:")
    print ("--run выполнение скрипта. Без этого параметра не выполняется.")
    exit(0)
arg=sys.argv[1]
if arg=="--run":
    print ("- подключаемся к ",server);
    mail = imaplib.IMAP4_SSL(server)
    print ("-- логинимся");
    mail.login(login, password)
    mail.list()
    print ("-- подключаемся к inbox");
    mail.select("inbox")
    print ("-- получаем UID последнего письма");
    result, data = mail.uid('search', None, "ALL")       
    try:
     latest_email_uid = data[0].split()[-1]     
    except IndexError:
     print("-- писем нет!");
     exit(0)
    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
    raw_email = data[0][1]
    try:
     email_message = email.message_from_string(raw_email)	
    except TypeError:
     email_message = email.message_from_bytes(raw_email)
    print ("--- нашли письмо от: ",email.header.make_header(email.header.decode_header(email_message['From'])));
    for part in email_message.walk():
        print(part.get_content_type())
        if "application" in part.get_content_type() :	    
            filename = part.get_filename()
            filename=str(email.header.make_header(email.header.decode_header(filename)))
            if not(filename): filename = "test.txt"          
            print ("---- нашли вложение ",filename);	    
            fp = open(os.path.join(putdir, filename), 'wb')
            fp.write(part.get_payload(decode=1))
            fp.close
    print ("-- удаляем письмо");
    mail.uid('STORE', latest_email_uid , '+FLAGS', '(\Deleted)')  
    mail.expunge()

Решение 2 (пролистываем весь ящик):

#!/usr/bin/env python3
#encoding: UTF-8
import sys
import imaplib
import email
import os

server = "mail.sgergser.ru"
port = "143"
login = "sergfsertg@ergser.ru"
password = "esrgser"
putdir="/home/esrgser/";

ver="1.0";
copyleft="(c) 2018 by Pavel Gribov http://грибовы.рф";
comment="Сей чудный скрипт смотрит почту по imap протоколу, сохраняет вложения в заданную папку, удаляет писмо с сервера";

# История изменений

##

print (ver);
print (copyleft);
print (comment);

if len(sys.argv)==1:
    print ("Возможные параметры:")
    print ("--run выполнение скрипта. Без этого параметра не выполняется.")
    exit(0)
arg=sys.argv[1]
if arg=="--run":
    print ("- подключаемся к ",server);
    mail = imaplib.IMAP4_SSL(server)
    print ("-- логинимся");
    mail.login(login, password)
    mail.list()
    print ("-- подключаемся к inbox");
    mail.select("inbox")
    print ("-- получаем UID последнего письма");
    result, data = mail.uid('search', None, "ALL")       
    
    for num in data[0].split() :
     result, data = mail.fetch(num, '(RFC822)')
     raw_email = data[0][1]    
     try:
      email_message = email.message_from_string(raw_email)	
     except TypeError:
      email_message = email.message_from_bytes(raw_email)
     print ("--- нашли письмо от: ",email.header.make_header(email.header.decode_header(email_message['From'])));
     for part in email_message.walk():
        print(part.get_content_type())
        if "application" in part.get_content_type() :	    
            filename = part.get_filename()
            filename=str(email.header.make_header(email.header.decode_header(filename)))
            if not(filename): filename = "test.txt"          
            print ("---- нашли вложение ",filename);	    
            fp = open(os.path.join(putdir, filename), 'wb')
            fp.write(part.get_payload(decode=1))
            fp.close
     print ("-- удаляем письмо");
     mail.store(num , '+FLAGS', '(\Deleted)')  
     mail.expunge()    
    mail.close()
    mail.logout();

Контроль касс Атол в Zabbix

Основная задача скрипта — вывести в консоль информацию об основных параметрах кассы, что бы агент заббикса мог как то распарсить данные.

Пример скрипта:

#!/usr/bin/python3.5
# -*- coding: utf-8 -*-
import base64
import ctypes
import sys
import json
import datetime
import os
import platform
from pprint import pprint

from lib import IFptr
#fptr = IFptr("")

#get extr param
if len(sys.argv)==1:
    print ("Возможные параметры:")
    print ("--info IP - общая информация о ККМ")
    exit(0)
arg=sys.argv[1]
if arg=="--info":
    ip=sys.argv[2];
    
LIBRARY_PATH = os.path.dirname(os.path.abspath(__file__))
fptr = IFptr(os.path.join(LIBRARY_PATH, "libfptr10.so"))
#connect to ATOL
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_MODEL, str(IFptr.LIBFPTR_MODEL_ATOL_AUTO))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_PORT, str(IFptr.LIBFPTR_PORT_TCPIP))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPADDRESS, ip)
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPPORT,"5555")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_ACCESS_PASSWORD,"0")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_USER_PASSWORD,"30")

fptr.applySingleSettings()
#открываем соединение
fptr.open()
isOpened = fptr.isOpened()
if isOpened==0:
    print ("9) Доступность:",0)
    exit(1)
    
if arg=="--info":
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_REG_INFO)
    fptr.fnQueryData()

    taxationTypes               = fptr.getParamInt(1062)
    agentSign                   = fptr.getParamInt(1057)
    ffdVersion                  = fptr.getParamInt(1209)
    print("Версия ФН:",ffdVersion)

    autoModeSign                = fptr.getParamBool(1001)
    offlineModeSign             = fptr.getParamBool(1002)
    encryptionSign              = fptr.getParamBool(1056)
    internetSign                = fptr.getParamBool(1108)
    serviceSign                 = fptr.getParamBool(1109)
    bsoSign                     = fptr.getParamBool(1110)
    lotterySign                 = fptr.getParamBool(1126)
    gamblingSign                = fptr.getParamBool(1193)
    exciseSign                  = fptr.getParamBool(1207)
    machineInstallationSign     = fptr.getParamBool(1221)
    fnsUrl                      = fptr.getParamString(1060)
    organizationVATIN           = fptr.getParamString(1018)
    organizationName            = fptr.getParamString(1048)
    organizationEmail           = fptr.getParamString(1117)
    paymentsAddress             = fptr.getParamString(1187)
    registrationNumber          = fptr.getParamString(1037)
    machineNumber               = fptr.getParamString(1036)
    ofdVATIN                    = fptr.getParamString(1017)
    ofdName                     = fptr.getParamString(1046)
    print("1) Организация:",organizationName)
    print("2) ОФД:",ofdName)
        
    fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_STATUS)
    fptr.queryData()
    serialNumber    = fptr.getParamString(IFptr.LIBFPTR_PARAM_SERIAL_NUMBER)
    modelName       = fptr.getParamString(IFptr.LIBFPTR_PARAM_MODEL_NAME)
    firmwareVersion = fptr.getParamString(IFptr.LIBFPTR_PARAM_UNIT_VERSION)
    print("3) S/N:",serialNumber)
    print("4) Модель:",modelName)
    print("5) Прошивка:",firmwareVersion)
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_VALIDITY)
    fptr.fnQueryData()
    dateTime            = fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
    print("6) Дата окончания ФН:",dateTime)
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_LAST_RECEIPT)
    fptr.fnQueryData()
    documentNumber      = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
    print("7) Номер чека:",documentNumber)
    # Получение информации о неотправленных документах
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_OFD_EXCHANGE_STATUS)
    res=fptr.fnQueryData()
    unsentCount = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENTS_COUNT)
    if unsentCount>0:
        unsentFirstNumber = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
        unsentDateTime = fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
        print ("8) Не фискализировано:",unsentCount)
        fptr.close()    
        del fptr
        exit(1)
    else:
        print ("8) Не фискализировано:",0)
    print ("9) Доступность:",1)

Пример выполнения:

root@pavel-All-Series:~/online_kassa# ./common.py --info 192.168.0.103
Версия ФН: 105
1) Организация: Индивидуальный предприниматель Пупкин Александр Владимирович
2) ОФД: ООО "Компания "Тензор"
3) S/N: 00103452021133752352
4) Модель: АТОЛ 55Ф
5) Прошивка: 1245
6) Дата окончания ФН: 2021-06-07 00:00:00
7) Номер чека: 414
8) Не фискализировано: 0
9) Доступность: 1

Пример оформления триггера в агенте zabbix:

UserParameter=ping_kassa,/home/pavel/online_kassa/common.py --info 192.168.0.103 | grep "9)" | awk '{print $3}'

UserParameter=non_fiskalize,/home/pavel/online_kassa/common.py --info 192.168.0.103 | grep "8)" | awk '{print $3}'

Работа с Атол 55Ф из python, ветка драйверов 10.х

В продолжение предыдущей статьи о работе с Атол чрез python. Там описывалась работа с драйверами из ветки ДТО 9.х Всё хорошо, но в них не поддерживаются «электронные чеки». Собственно из-за чего всё и затевалось у меня. К сожалению работа с драйверами 10.х существенно отличается от 9.х Но к счастью есть ресурс http://integration.atol.ru, в котором достаточно всё хорошо разжевано с примерами. Правда без учета специфики Linux.

Итак, что нужно для того что-бы «поработать» с драйверами в Ubuntu.

1) Штатно установить драйвера deb из папки installer
2) В зависимости от того, скольки битная система, скопировать в папку проекта содержимое linux-86 или linux-x64. Если драйвера установлены верно, то при запуске fptr10_t.sh можно будет увидеть что-то вроде:

3) В архиве с драйверами ищем libfptr10.py и копируем в файл проекта python

4) Далее если мы будем для инициализации драйвера использовать код из примеров вида:

#!/usr/bin/python2
# -*- coding: utf-8 -*-


import sys
import os
from libfptr10 import IFptr


, то получим ошибку:

root@pavelpc:~/reserved/getcoding/atol/test/ver10# ./kkt_10.py
Traceback (most recent call last):
  File "./kkt_10.py", line 7, in <module>
    from libfptr10 import IFptr
ImportError: dynamic module does not define init function (initlibfptr10)

На сколько мне, не сильно подкованному в python и cpp, удалось выяснить, проблема в не верно скомпилированном libfptr10.so Возможно в следующих версиях драйвера она уйдет.

А пока, выходом у меня является дописание функционального кода в конце файла libfptr10.py, после описания класса IFptr

Например:

LIBRARY_PATH = os.path.dirname(os.path.abspath(__file__))
fptr = IFptr(os.path.join(LIBRARY_PATH, "libfptr10.so"))
print (fptr)

fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_MODEL, str(IFptr.LIBFPTR_MODEL_ATOL_55F))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_PORT, str(IFptr.LIBFPTR_PORT_TCPIP))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPADDRESS, "192.168.0.99")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPPORT,"5555")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_LIBRARY_PATH,"/home/pavel/reserved/getcoding/atol/test/ver10")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_ACCESS_PASSWORD,"0")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_USER_PASSWORD,"30")
res=fptr.applySingleSettings()
print (res);

fptr.open()

isOpened = fptr.isOpened()
print ("Opened:"+str(isOpened));

fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_STATUS)
fptr.queryData()
operatorID      = fptr.getParamInt(IFptr.LIBFPTR_PARAM_OPERATOR_ID)
print (operatorID)
logicalNumber   = fptr.getParamInt(IFptr.LIBFPTR_PARAM_LOGICAL_NUMBER)
shiftState      = fptr.getParamInt(IFptr.LIBFPTR_PARAM_SHIFT_STATE)
serialNumber    = fptr.getParamString(IFptr.LIBFPTR_PARAM_SERIAL_NUMBER)
modelName       = fptr.getParamString(IFptr.LIBFPTR_PARAM_MODEL_NAME)
firmwareVersion = fptr.getParamString(IFptr.LIBFPTR_PARAM_UNIT_VERSION)
print (modelName)

Кое-что уже выводит:

Вызов скрипта на python из php с передачей произвольных данных

Редко,  но бывает необходимо из скрипта на PHP, вызвать на исполнение скрипт на python с передачей неких параметров и данных.

Мне например понадобилось потому что основной код у меня на PHP,  а вот часть которая отвечает за взаимодействие с онлайн кассой Атол — на python, и переписывать эту часть на PHP нет возможности (без большого гемороя) —  заголовки драйвера Атола под Linux есть только на python (dto9fptr.py и dto9base.py — поставляются в комплекте с драйвером).

Ниже приведен один из способов:

PHP:

<?php

$idkkm= _POST("idkkm");

$sql = "SELECT * FROM online_kkm where id='$idkkm'";
$result = $sqlcn->ExecuteSQL($sql) or die("Не могу выбрать список настроек!" . mysqli_error($sqlcn->idsqlconnection));
$param=array();
$param["mode"]="getinfo";
while ($row = mysqli_fetch_array($result)) {
    $param["ipaddress"] = $row['ipaddress'];
    $param["ipport"] = $row['ipport'];
    $param["model"] = $row['model'];
    $param["accesspass"] = $row['accesspass'];
    $param["userpass"] = $row['userpass'];
    $param["protocol"] = $row['protocol'];
    $param["logfilename"] = $row['logfilename'];
    $param["testmode"] = $row['testmode'];
    $param["libpath"] = $row['libpath'];
    $param["version"] = $row['version'];
    $ppath= $row['ppath'];
};
$jsonparam= base64_encode(json_encode($param));
$command = "/usr/bin/env python $ppath $jsonparam 2>&1";
$pid = popen( $command,"r");
while( !feof( $pid ) )
{
 echo fread($pid, 256);
 flush();
 ob_flush();
 usleep(100000);
}
pclose($pid);

?>

Python:

#!/usr/bin/env python2
#encoding: UTF-8
import sys, json,base64

prm=json.loads(base64.b64decode(sys.argv[1]))

print prm["ipaddress"]

Т.е. что мы сделали?

  1. В скрипте на PHP сформировали json строку с параметрами и закодировали её в base64
  2. Вызвали python скрипт с аргументом в кодированной строки
  3. Python скрипт соответственно обратно декодирует и обрабатывает json

Профит.