Архив рубрики: 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();

Работа с Атол 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)

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

Фискализация чеков через онлайн-кассу АТОЛ 55Ф на ОС Ubuntu, python

Прилетела задача фискализировать поступления платежей через оплату услуг с карточек через интернет, из личного кабинета абонента, оплаты абонента посредством Сбербанк-онлайн и т.п. Из ТУ : операционная система семейства Linux.

Было рассмотрено несколько вариантов решения:

1) Сервис Атол-Онлайн. Плюсы: простота интеграции, очень вменяемое API. Минусы — со второго года — выходит очень дорого по сравнению со «своей железкой»

2)PAYONLINE-01-ФА. Плюсы: прям в «базе» нет принтера, что удешевляет. Минусы: нет толкового описания работы с драйверами, примеров, нет драйверов под LInux

3) Атол-55Ф. Плюсы: драйвера под Linux, вменяемое описание работы с примерами на Java, cpp. Плюс натолкнулся на пример работы https://github.com/parshin/kkt с этой железкой. Минусы — дорого по сравнению с 2) но дешево по сравнению с 1)

Собственно драйвера ставятся стандартно. Далее пример пробития чека на python

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

# import web
import sys
import os
import json
import logging

from conf import *	    # загружаем настройки
import dto9fptr		    # загружаем заголовки драйвера

def DeviceSetup(driver,params):    
    driver.put_DeviceSingleSetting("Port", params["Port"])
    driver.put_DeviceSingleSetting("IPAddress", params["IPAddress"])
    driver.put_DeviceSingleSetting("IPPort", params["IPPort"])
    driver.put_DeviceSingleSetting("Model", params["Model"])
    driver.put_DeviceSingleSetting("Protocol", params["Protocol"])
    driver.put_DeviceSingleSetting("AccessPassword", params["AccessPassword"])
    driver.put_DeviceSingleSetting("UserPassword", params["UserPassword"])
    driver.put_DeviceSingleSetting("Protocol", params["Protocol"])
    driver.put_DeviceSingleSetting('SearchDir', os.path.dirname(DTO_LIB_NAME))
    driver.ApplySingleSettings()
    driver.put_DeviceEnabled(True)
    return 0

def GetCurrentParamDevice(driver):
    result = driver.GetStatus()    
    if result[0]!=0:
	print t_err+unicode(result[1])+t_off
	logging.info(result[1])
	exit(1)
    result = driver.get_DeviceSettings()
    print t_mess+'Текщие настройки: '+t_off + str(result)
    if str(result)=="None":
	etxt="Драйвер не подключился к устройству"
	print t_err+etxt+t_off
	logging.info(etxt)
	exit(1)
    return result

def print_check(driver, check_data):
    res=0
    mess="check_data: " + str(check_data)
    
    print t_mess+mess+t_off
    logging.info(mess)
    
    result = driver.put_DeviceEnabled(True)
    logging.info("put device enabled: " + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code != 0:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	print t_err+str(result_code)+t_off
	print t_err+result_description+t_off
        exit(1)  
    print t_ok+result_description+t_off		
    
    print t_mess+"- переводим ККМ в режим регистрации"+t_off
    result = driver.put_Mode(1)
    logging.info("put mode 1:" + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code != 0:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	print t_err+str(result_code)+t_off
	print t_err+result_description+t_off
    print t_ok+result_description+t_off					   
	
    print t_mess+"- создаем новый документ"+t_off
    result = driver.NewDocument()	
    logging.info("new document:" + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code == -3822:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
        logging.error("  trying close shift...")
	print t_err+str(result_code)+t_off
	print t_err+result_description+t_off
	exit(1)
    print t_ok+result_description+t_off	
    
    print t_mess+"- выставляем что тип чека - продажа"+t_off
    result = driver.put_CheckType(1)
    logging.info("put check type:" + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code != 0:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	print t_err+str(result_code)+t_off
	print t_err+result_description+t_off
	exit(1)
    print t_ok+result_description+t_off	
	
    print t_mess+"- открываем чек"+t_off
    result = driver.OpenCheck()
    logging.info("open check:" + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code != 0:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	print t_err+str(result_code)+t_off
	print t_err+result_description+t_off
	exit(1)
    print t_ok+result_description+t_off	
    
    print t_mess+"- регистрация позиций"+t_off
    logging.info("registering positions...")
    
    for position in check_data:
	print "--- №:"+str(position["num"])
	print "--- Дата:"+str(position["docdate"])
	print "--- Всего:"+str(position["summdoc"])
	for goods in position["goods"]:
	    print "---- Товар:"+str(goods["name"])
	    result = driver.put_Name(goods["name"].decode('utf8'))
	    print "---- Цена:"+str(goods["price"])
	    result = driver.put_Price(goods["price"])
	    print "---- Количество:"+str(goods["quiantity"])
	    result = driver.put_Quantity(goods["quiantity"])
	    result = driver.put_TaxNumber(3) 
	    print "---- Сумма:"+str(goods["summ"])
	    result_code = driver.put_PositionSum(goods["summ"]) 
	    print "---- Регистрация позиции:"
	    result_code = driver.Registration() 	    
	    if result_code[0] != 0:
		logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
		logging.error("  result description:" + repr(result_description).decode("unicode_escape"))	    
		print t_err+str(result_code)+t_off
		print t_err+result_description+t_off
		exit(1)
	

	print t_mess+"- прием оплаты"+t_off
	result = driver.put_TypeClose(1)  # Тип оплаты - Платежная карта
	logging.info("put type close:" + repr(result).decode("unicode_escape"))
	result_code = driver.get_ResultCode()
	result_description = driver.get_ResultDescription()
	if result_code != 0:
	    logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
	    logging.error("  result description:" + repr(result_description).decode("unicode_escape"))	    
	    print t_err+str(result_code)+t_off
	    print t_err+result_description+t_off
	    exit(1)

	print t_mess+"- сумма оплаты"+t_off
	result = driver.put_Summ(position["summdoc"])
	logging.info("put summ:" + repr(result).decode("unicode_escape"))
	result_code = driver.get_ResultCode()
	result_description = driver.get_ResultDescription()
	if result_code != 0:
	    logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
	    logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	    print t_err+str(result_code)+t_off
	    print t_err+result_description+t_off
	    exit(1)

	print t_mess+"- регистрация платежа"+t_off
	result = driver.Payment()
	logging.info("pyment:" + repr(result).decode("unicode_escape"))
	result_code = driver.get_ResultCode()
	result_description = driver.get_ResultDescription()
	if result_code != 0:
	    logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
	    logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	    print t_err+str(result_code)+t_off
	    print t_err+result_description+t_off
	    exit(1)

	print t_mess+"- проверка фиксации "+t_off
	result = driver.get_ResultCode()
	logging.info("payment result code:" + repr(result).decode("unicode_escape"))
	result_code = driver.get_ResultCode()
	result_description = driver.get_ResultDescription()
	if result_code != 0:
	    logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
	    logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
	    print t_err+str(result_code)+t_off
	    print t_err+result_description+t_off
	    exit(1)

    print t_mess+"- закрытие чека "+t_off
    result = driver.CloseCheck()
    logging.info("close check:" + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code != 0:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
        print t_err+str(result_code)+t_off
        print t_err+result_description+t_off
        exit(1)

    print t_mess+"- получение номера чека "+t_off
    result = driver.get_CheckNumber()
    logging.info("check number:" + repr(result).decode("unicode_escape"))
    result_code = driver.get_ResultCode()
    result_description = driver.get_ResultDescription()
    if result_code != 0:
        logging.error("  result code:" + repr(result_code).decode("unicode_escape"))
        logging.error("  result description:" + repr(result_description).decode("unicode_escape"))
        print t_err+str(result_code)+t_off
        print t_err+result_description+t_off
        exit(1)


    exit(1)
    return res

os.environ['LD_LIBRARY_PATH'] = os.path.dirname(os.path.realpath(__file__))
logging.info(os.path.dirname(os.path.realpath(__file__)))
logging.info(os.environ)

print t_mess+"Фискализация чеков v 1.0 (c) 2018 by Pavel Gribov http://грибовы.рф"+t_off

DTO_LIB_NAME = '/opt/ATOL/drivers9/bin/libfptr.so'
VERSION = 15
driver = dto9fptr.Fptr(DTO_LIB_NAME, VERSION)

print t_mess+"Драйвер:"+t_off+str(driver)
print t_mess+"Параметры:"+t_off+str(params)

# устанавливаем параметры соединения
DeviceSetup(driver,params)
# Читаем текущие настройки
cursettings=GetCurrentParamDevice(driver)
# печатаем чек
check_data=[]

goodsa=[]
goodsa.append({"name":"Телематические услуги связи 1","price":0.01,"quiantity":1,"summ":0.01});
goodsa.append({"name":"Телематические услуги связи 2","price":0.01,"quiantity":1,"summ":0.01});

check_data.append({"num":"1","docdate":"07.05.2018","summdoc":0.02,"goods":goodsa});

print check_data
print_check(driver, check_data)

driver.Beep()


#Закончили работу
driver.put_DeviceEnabled(False)
del driver

conf.py:

params = {
    "Port": "TCPIP",
    "IPAddress": "192.168.0.99",
    "IPPort": "5555",
    "Model": "62",
    "AccessPassword": "0",
    "UserPassword": "30",
    "Protocol": "2",
    "LogFileName": "/var/log/kkt.log"
}
t_mess="\x1b[33m"
t_err="\x1b[31m"
t_ok="\x1b[32m"
t_off="\x1b[0m"

Далее осталась рутина, отключить физическую печать, доделать автоматическое открытие-закрытие смены и т.п. Но в принципе всё уже есть в https://github.com/parshin/kkt

В файле conf.py нужно прописать параметры подключения к ККТ IP адрес, порт, путь к лог файлу и т.д. Параметр «Model» смотрим в Руководстве программиста приложение 7 модели ККМ ???(у меня 47 не подошло, подошло 62, почему не понял).

VERSION = 15 — это для драйверов 9.12.1. Возможно потом нужно будет менять на 16 и т.д.

P.S. Решение применимо и для других аппаратов АТОЛ с минимальными изменениями.

Python. Получение списка IP по hostname

Задача: по извесному доменному имени получить список его IP адресов

Решение:

#!/usr/bin/python
# coding=utf-8
import sys
import socket
import dns.resolver

site = "www.google.com"
dns_server = "8.8.8.81"

try:
    resolver = dns.resolver.Resolver()
    resolver.nameservers = [socket.gethostbyname(dns_server)]
    resolver.timeout = 1
    resolver.lifetime = 1
    answer = resolver.query(site, 'A');
    for rdata in answer :
        print rdata.address
except:
    print "Ошибка получения списка IP";

Python и Mysql — получение последнего вставленного ID

Ну проще всего показать на примере:

def InsertUserToForpost(connf,login,passw):
    putlog("*добавляем учетку в Форпост "+str(login));    
    sql="insert into User (ID,IsActive,CanChangeOwnInfo,CreationDate,Login,Password,TypeId) values (null,1,1,now(),%s,MD5(%s),2);";
    cursor = connf.cursor(dictionary=True,buffered=True)
    cursor.execute(sql,[login,passw]);
    connf.commit()
    #получаем ID
    lid=conf.insert_id()
    sql="insert into AccountUser (ID,UserID,AccountID,IsReadOnly) VALUES (null,%s,1,1);";
    cursor = connf.cursor(dictionary=True,buffered=True)
    cursor.execute(sql,[lid]);