使用 python docx 时 Python Flask GAE 中出现管道损坏错误

发布于 2025-01-13 17:31:38 字数 19537 浏览 1 评论 0原文

我有一个 Flask 应用程序,它使用 Python-docx 来自动化公司中的某些文档。我的 Flask 应用程序部署在 Google App Engine 标准环境中。 我经常遇到这个错误: Broken Pipe

我搜索到的大多数找到此问题解决方案的文章都使用

signal(SIGPIPE,SIG_DFL)

,但使用此解决方案时,我仍然收到 Broken Pipe 错误。

需要一些帮助,请

编辑: 我是编码新手,所以请放轻松 基本上我想做的是为公司中的每个人注册一个数字签名。此一次性签名会生成一个 6 位数的令牌,在想要签署文档时将使用该令牌。当用户注册签名时,除了收到带有令牌的电子邮件外,他们还会收到一个 pdf 附件,该附件是他们必须打印并签名以授权其数字签名的文档。

@app.route('/registro_firma_digital', methods=['GET','POST'])
def registro_firma_digital():
signal(SIGPIPE,SIG_DFL)
unix_socket = '/cloudsql/{}'.format(db_connection_name)
cnx = pymysql.connect(user=db_user, password=db_password,
                            unix_socket=unix_socket, db=db_name)
mycursor = cnx.cursor()

unix_socket2 = '/cloudsql/{}'.format(db_connection_name)
cnx2 = pymysql.connect(user=db_user, password=db_password,
                                unix_socket=unix_socket2, db="sedial")


mycursor2 = cnx2.cursor()

try:
    signal(SIGPIPE,SIG_DFL)
    if 'user' in session:
        dateTimeObjr = datetime.date.today()
        dateTimeObj = dateTimeObjr.strftime('%Y-%m-%d')

        if request.method == "POST":
            
        


            #get datestamp
            

            data = request.form['dataurl']
            cc = str(request.form['cedula']).strip()
            nombre = request.form['name']
            email = str(request.form['email']).strip()


            mycursor2.execute(<sql sentence>)
            cc_presente = mycursor2.fetchone()

            if not cc_presente:
                return render_template('cc_no_presente.html', cedula=cc)
            
            
            user = session['user']
            

            #allow only one registration per id
            

            #generate random string for our token
            S = 6  # number of characters in the string.
            llave = ''.join(random.choices(string.digits, k=S))

            l = 10  # number of characters in the string.
            tiquete = ''.join(random.choices(string.digits, k=l))
            #the token is sent to the user in its orignal format, but for security reasons we convert the token to hash for our database
            h = hashlib.md5(llave.encode())
            hash_token = h.hexdigest()

            preg1 = request.form['preg1']
            h_preg1 = hashlib.md5(preg1.encode())
            hash_token_preg1 = h_preg1.hexdigest()

            preg2 = request.form['preg2']
            h_preg2 = hashlib.md5(preg2.encode())
            hash_token_preg2 = h_preg2.hexdigest()

            preg3 = request.form['preg3']
            h_preg3 = hashlib.md5(preg3.encode())
            hash_token_preg3 = h_preg3.hexdigest()

            preg4 = request.form['preg4']
            h_preg4 = hashlib.md5(preg4.encode())
            hash_token_preg4 = h_preg4.hexdigest()
            
            #validate the the hash token doesnt already exist, if it does it generates another. (not likely to happen)
            mycursor.execute(
                "select * from banco_firmas_digitales where llave = '"+str(hash_token)+"'")
            key_present = mycursor.fetchone()
            if key_present:

                l = S + 1
                llave = ''.join(random.choices(string.digits, k=l))
                h = hashlib.md5(llave.encode())
                hash_token = h.hexdigest()

            mycursor.execute(<sql sentence>)
            key_present = mycursor.fetchone()
            if key_present:

                m = l + 1
                tiquete = ''.join(random.choices(string.digits, k=m))
               



            mycursor.execute(<sql sentence>)
            

            bucket = storage_client.get_bucket('<bucketname>')
           
            blob = bucket.blob("<blob").download_as_string()
            doc_obj = Document(io.BytesIO(blob))
           
            
            img_blob = str(data)

            encoded = re.sub("b'", "", img_blob)
            encoded = re.sub("'", "", encoded)



            image_64_decode = base64.b64decode(encoded) 
            image_result = open('/tmp/pic.png', 'wb') # create a writable image and write the decoding result
            image_result.write(image_64_decode)


            tables = doc_obj.tables
            p = tables[0].rows[1].cells[0].paragraphs[0]
            r = p.add_run()
            
            r.add_picture('/tmp/pic.png',width=Inches(3.74), height=Inches(1.96))
            p.alignment = 1

            filename = "firma_digital_hv.docx"
            doc_obj.save("/tmp/"+filename)



            pathe = "/tmp"
            
            filename_path = pathe+"/"+filename

            file_metadata = {'name': filename_path,
                                'mimeType': 'application/vnd.google-apps.document'}

            media = MediaFileUpload(filename_path,
                                    mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
            file = drive.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
                    
            print('File ID: %s' % file.get('id'))
            fileid = file.get('id')            
                
            request_ = drive.files().export_media(fileId=fileid,
                                mimeType='application/pdf')
            fh = io.BytesIO()
            downloader = MediaIoBaseDownload(fd=fh, request=request_)
            done = False
            while done is False:
                status, done = downloader.next_chunk()
                
            fh.seek(0)
            file_name = '/tmp/'+fileid+'.pdf'
            with open(file_name, 'wb') as fx:
                fx.write(fh.read())

    

            cnx.commit()
        

            from_addr = "<fromemail>"
            password = "<password>"
            to_addr = email
                    
            subject = "Detalle Registro Firmal Digital"
            content = ""
            text = """\
    Hi,
    How are you?
    Real Python has many great tutorials:
    www.realpython.com
        """
            html = """\
    <!DOCTYPE html>
    <html>

    <head>
        <title>Registro Firma Digital</title>
        <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css"
            integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
        <style>
            html,
            body {
                min-height: 100%;
                background-color: black;
            }

            body,
            div,
            form,
            select,
            textarea,
            label {
                padding: 0;
                margin: 0;
                outline: none;
                font-family: Roboto, Arial, sans-serif;
                font-size: 14px;
                color: white;
                line-height: 22px;
            }

            input {
                padding: 0;
                margin: 0;
                outline: none;
                font-family: Roboto, Arial, sans-serif;
                font-size: 14px;
                color: black;
                line-height: 22px;
            }



            legend {
                padding: 10px;
                font-family: Roboto, Arial, sans-serif;
                font-size: 18px;
                color: rgb(0, 68, 255);
                box-shadow: 0 0 8px rgb(0, 68, 255);
            }

            textarea {
                width: calc(100% - 12px);
                padding: 5px;
            }

            .testbox {
                display: flex;
                justify-content: center;
                align-items: center;
                height: inherit;
                padding: 20px;
            }

            form {
                width: 100%;
            
                padding: 20px;
                border-radius: 6px;
                background: #000;
                box-shadow: 0 0 8px rgb(0, 68, 255);
            }



            input,
            select,
            textarea {
                margin-bottom: 10px;
                border: 1px solid #ccc;
                border-radius: 3px;
            }

            input {
                width: calc(100% - 10px);
                padding: 5px;
            }

            input[type="date"] {
                padding: 4px 5px;
            }

            textarea {
                width: calc(100% - 12px);
                padding: 5px;
            }

            .item:hover p,
            .item:hover i,
            .question:hover p,
            .question label:hover,
            input:hover::placeholder {
                color: rgb(0, 68, 255);
            }

            .item input:hover,
            .item select:hover,
            .item textarea:hover {
                border: 1px solid transparent;
                box-shadow: 0 0 3px 0 rgb(0, 68, 255);
                color: rgb(0, 68, 255);
            }

            .item {
                position: relative;
                margin: 10px 0;
            }

            .item span {
                color: red;
            }

            input[type="date"]::-webkit-inner-spin-button {
                display: none;
            }

            .item i,
            input[type="date"]::-webkit-calendar-picker-indicator {
                position: absolute;
                font-size: 20px;
                color: black;
            }

            .item i {
                right: 1%;
                top: 30px;
                z-index: 1;
            }

            .week {
                display: flex;
                justify-content: space-between;
            }

            .columns {
                display: flex;
                justify-content: space-between;
                flex-direction: row;
                flex-wrap: wrap;
            }

            .columns div {
                width: 228%;
            }

            [type="date"]::-webkit-calendar-picker-indicator {
                right: 1%;
                z-index: 2;
                opacity: 0;
                cursor: pointer;
            }

            input[type=radio],
            input[type=checkbox] {
                display: none;
            }

            label.radio {
                position: relative;
                display: inline-block;
                margin: 5px 20px 15px 0;
                cursor: pointer;
            }

            .question span {
                margin-left: 30px;
            }

            .question-answer label {
                display: block;
            }

            label.radio:before {
                content: "";
                position: absolute;
                left: 0;
                width: 17px;
                height: 17px;
                border-radius: 50%;
                border: 2px solid #ccc;
            }

            input[type=radio]:checked+label:before,
            label.radio:hover:before {
                border: 2px solid rgb(0, 68, 255);
            }

            label.radio:after {
                content: "";
                position: absolute;
                top: 6px;
                left: 5px;
                width: 8px;
                height: 4px;
                border: 3px solid #006622;
                border-top: none;
                border-right: none;
                transform: rotate(-45deg);
                opacity: 0;
            }

            input[type=radio]:checked+label:after {
                opacity: 1;
            }

            .flax {
                display: flex;
                justify-content: space-around;
            }

            .btn-block {
                margin-top: 10px;
                text-align: center;
            }


            @media (min-width: 568px) {

                .name-item,
                .city-item {
                    display: flex;
                    flex-wrap: wrap;
                    justify-content: space-between;
                }

                .name-item input,
                .name-item div {
                    width: calc(50% - 20px);
                }

                .name-item div input {
                    width: 97%;
                }

                .name-item div label {
                    display: block;
                    padding-bottom: 5px;
                }
            }
        </style>
    </head>

    <body>
        <div class="testbox">


            <form align="center">
                <div class="banner">
                    <aside> <img class="demo" src="https://i.ibb.co/ws5rF2w/SEDIAL.png" width="200" height="80"></aside>

                

                </div>
                <br />
                <fieldset>
                    <legend>Detalle</legend>

                    <div align="center">

                    <div class="form-group">
                        <label class="item"><strong>Token Firma Digital: </strong>"""+str(llave)+"""</label>
                        <p>----------------------------------------------------</p>
                        </div>

                    <div class="form-group">
                        <label class="item"><strong>PASO 1:</strong></label>
                        <p>Descargar e imprimir el formato adjunto al correo</p>
                        </div>

                        <div class="form-group">
                        <label class="item"><strong>PASO 2:</strong></label>
                        <p>Llenar los campos requeridos del documento (Firma del testigo es quien te acompaño durante el registro)</p>
                        </div>

                        <div class="form-group">
                        <label class="item"><strong>PASO 3:</strong></label>
                        <p>Escanear el documento</p>
                        </div>

                        <div class="form-group">
                        <label class="item"><strong>PASO 4:</strong></label>
                        <p>Copiar la siguiente llave para el cargue del archivo: """+str(tiquete)+"""</p>
                        </div>
                        
                    <div class="form-group">
                        <label class="item"><strong>PASO 5:</strong></label>
                        <p>Ingresar al siguiente <a href="https://vernal-acrobat-301119.uc.r.appspot.com/carga_procedimiento_firmadigital_firmado">link</a> para subir el archivo escaneado</p>
                        </div>
                        
                    
                <p>--------------------------------------------------------------------------------------</p>
                <p><strong>*DECIMOSEXTA: FIRMA DIGITAL.-*</strong></p>
                <p>Para toda la documentación interna de la empresa, se utilizará una firma digital, la cual tendrá la misma validez que la firma caligráfica para todos los efectos internos y legales, incluyendo pero no limitándose a:</p>
                <p><strong>1. </strong>Recibo de documentación.</p>
                <p><strong>2. </strong>Firma de Otrosí al contrato laboral.</p>
                <p><strong>3. </strong>Firma de recibido de evaluaciones de desempeño.</p>
                <p><strong>4. </strong>Firma de procesos disciplinarios.</p>
                <p></p>
                <p>El empleado con la firma del presente documento declara que entiende y reconoce lo siguiente:</p>
                <p><strong>1. </strong>La firma digital podrá ser utilizada únicamente con el token que le será entregado por parte de la empresa mediante correo electrónico dirigido a la dirección que el empleado registre en los formularios FR-GH-002 “Ficha Básica” y FR-SF-012 “Actualización de Datos”.</p>
                <p><strong>2. </strong>El uso del token es personal e intransferible.</p>
                <p><strong>3. </strong>El empleado es el único responsable de la custodia y cuidado del token.</p>
                <p><strong>4. </strong>En virtud de lo anterior cualquier documento que esté firmado en el sistema Dashboard Sedial, se entiende firmado por el empleado.</p>
        
    </div>
                </fieldset>
    <div class="btn-block">

               
            </div>
            </form>
        </div>
            

    </body>

    </html>



        """
            msg = MIMEMultipart("alternative", None, [MIMEText(text), MIMEText(html,'html')])
            part1 = MIMEText(text, "plain")
            part2 = MIMEText(html, "html")
            msg.attach(part1)
            msg.attach(part2)
                    

        
                        
            msg['From'] = from_addr
            #msg['To'] = ", ".join(to_addr)
            msg['To'] = to_addr 
            msg['Subject'] = subject
            file_name_final = 'FR-GH-084_REGISTRO_FIRMA_DIGITAL_'+str(cc)+'_'+str(dateTimeObj)+'.pdf'

            with open(file_name, 'rb') as f:
                attachment = MIMEApplication(f.read(), Name=file_name_final)
                attachment['Content-Disposition'] = 'attachment; file_name="{}"'.format(file_name_final)

                        
            msg.attach(attachment)
            context = ssl.create_default_context()
            server = smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context)
            server.login(from_addr,password)
            server.send_message(msg, from_addr, to_addr)


            time.sleep(1)

            

            gcs = storage.Client()
            bucket = gcs.get_bucket("<buckename>")
            
            old_file = os.path.join(pathe, fileid+".pdf")
            newfilename = 'FR-GH-084_REGISTRO_FIRMA_DIGITAL_'+str(cc)+'_'+str(dateTimeObj)+'.pdf'
            new_file = os.path.join(pathe, newfilename)
            os.rename(old_file, new_file)   

            blob = bucket.blob("firmas_digitales/"+str(cc)+"/"+newfilename)
            blob.upload_from_filename(
                    os.path.join(pathe, newfilename)
                )    

            mycursor.execute(<sql sentence>)    


            cnx.commit()

            #execute deleteemail function to avoid me have access to raw token
            deletesubject = "Detalle Registro Firmal Digital"
            deleteemail(deletesubject) 

            return redirect(url_for('registro_firma_digital'))
        return render_template('registro_firma_digital.html')
    else:
        return redirect(url_for('login'))
except Exception as e:
    if 'Duplicate entry' in str(e):
        return render_template('cc_firma_presente.html', cc=cc)
    else:    
        return str(e)
finally:
    cnx.close()
    cnx2.close()

I have a flask app that uses Python-docx to automate certain documents in my company. I have my flask app deployed in Google App Engine Standard Environment.
Ive been getting this error a lot:
Broken Pipe

Most articles I searched that found a solution to this use the

signal(SIGPIPE,SIG_DFL)

, but using this solution, I am still getting the Broken Pipe Error.

Could use some help please

EDIT:
I am new at coding so please go easy on me
basically what I am trying to do is register a digital signature for everyone in the company. This one time signature generates a 6 digit token that will be used when wanting to sign a document. When the user registers their signature, apart from getting an email with the token, they also get a pdf attachment which is a document they have to print and sign to authorize their digital signature.

@app.route('/registro_firma_digital', methods=['GET','POST'])
def registro_firma_digital():
signal(SIGPIPE,SIG_DFL)
unix_socket = '/cloudsql/{}'.format(db_connection_name)
cnx = pymysql.connect(user=db_user, password=db_password,
                            unix_socket=unix_socket, db=db_name)
mycursor = cnx.cursor()

unix_socket2 = '/cloudsql/{}'.format(db_connection_name)
cnx2 = pymysql.connect(user=db_user, password=db_password,
                                unix_socket=unix_socket2, db="sedial")


mycursor2 = cnx2.cursor()

try:
    signal(SIGPIPE,SIG_DFL)
    if 'user' in session:
        dateTimeObjr = datetime.date.today()
        dateTimeObj = dateTimeObjr.strftime('%Y-%m-%d')

        if request.method == "POST":
            
        


            #get datestamp
            

            data = request.form['dataurl']
            cc = str(request.form['cedula']).strip()
            nombre = request.form['name']
            email = str(request.form['email']).strip()


            mycursor2.execute(<sql sentence>)
            cc_presente = mycursor2.fetchone()

            if not cc_presente:
                return render_template('cc_no_presente.html', cedula=cc)
            
            
            user = session['user']
            

            #allow only one registration per id
            

            #generate random string for our token
            S = 6  # number of characters in the string.
            llave = ''.join(random.choices(string.digits, k=S))

            l = 10  # number of characters in the string.
            tiquete = ''.join(random.choices(string.digits, k=l))
            #the token is sent to the user in its orignal format, but for security reasons we convert the token to hash for our database
            h = hashlib.md5(llave.encode())
            hash_token = h.hexdigest()

            preg1 = request.form['preg1']
            h_preg1 = hashlib.md5(preg1.encode())
            hash_token_preg1 = h_preg1.hexdigest()

            preg2 = request.form['preg2']
            h_preg2 = hashlib.md5(preg2.encode())
            hash_token_preg2 = h_preg2.hexdigest()

            preg3 = request.form['preg3']
            h_preg3 = hashlib.md5(preg3.encode())
            hash_token_preg3 = h_preg3.hexdigest()

            preg4 = request.form['preg4']
            h_preg4 = hashlib.md5(preg4.encode())
            hash_token_preg4 = h_preg4.hexdigest()
            
            #validate the the hash token doesnt already exist, if it does it generates another. (not likely to happen)
            mycursor.execute(
                "select * from banco_firmas_digitales where llave = '"+str(hash_token)+"'")
            key_present = mycursor.fetchone()
            if key_present:

                l = S + 1
                llave = ''.join(random.choices(string.digits, k=l))
                h = hashlib.md5(llave.encode())
                hash_token = h.hexdigest()

            mycursor.execute(<sql sentence>)
            key_present = mycursor.fetchone()
            if key_present:

                m = l + 1
                tiquete = ''.join(random.choices(string.digits, k=m))
               



            mycursor.execute(<sql sentence>)
            

            bucket = storage_client.get_bucket('<bucketname>')
           
            blob = bucket.blob("<blob").download_as_string()
            doc_obj = Document(io.BytesIO(blob))
           
            
            img_blob = str(data)

            encoded = re.sub("b'", "", img_blob)
            encoded = re.sub("'", "", encoded)



            image_64_decode = base64.b64decode(encoded) 
            image_result = open('/tmp/pic.png', 'wb') # create a writable image and write the decoding result
            image_result.write(image_64_decode)


            tables = doc_obj.tables
            p = tables[0].rows[1].cells[0].paragraphs[0]
            r = p.add_run()
            
            r.add_picture('/tmp/pic.png',width=Inches(3.74), height=Inches(1.96))
            p.alignment = 1

            filename = "firma_digital_hv.docx"
            doc_obj.save("/tmp/"+filename)



            pathe = "/tmp"
            
            filename_path = pathe+"/"+filename

            file_metadata = {'name': filename_path,
                                'mimeType': 'application/vnd.google-apps.document'}

            media = MediaFileUpload(filename_path,
                                    mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
            file = drive.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
                    
            print('File ID: %s' % file.get('id'))
            fileid = file.get('id')            
                
            request_ = drive.files().export_media(fileId=fileid,
                                mimeType='application/pdf')
            fh = io.BytesIO()
            downloader = MediaIoBaseDownload(fd=fh, request=request_)
            done = False
            while done is False:
                status, done = downloader.next_chunk()
                
            fh.seek(0)
            file_name = '/tmp/'+fileid+'.pdf'
            with open(file_name, 'wb') as fx:
                fx.write(fh.read())

    

            cnx.commit()
        

            from_addr = "<fromemail>"
            password = "<password>"
            to_addr = email
                    
            subject = "Detalle Registro Firmal Digital"
            content = ""
            text = """\
    Hi,
    How are you?
    Real Python has many great tutorials:
    www.realpython.com
        """
            html = """\
    <!DOCTYPE html>
    <html>

    <head>
        <title>Registro Firma Digital</title>
        <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css"
            integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
        <style>
            html,
            body {
                min-height: 100%;
                background-color: black;
            }

            body,
            div,
            form,
            select,
            textarea,
            label {
                padding: 0;
                margin: 0;
                outline: none;
                font-family: Roboto, Arial, sans-serif;
                font-size: 14px;
                color: white;
                line-height: 22px;
            }

            input {
                padding: 0;
                margin: 0;
                outline: none;
                font-family: Roboto, Arial, sans-serif;
                font-size: 14px;
                color: black;
                line-height: 22px;
            }



            legend {
                padding: 10px;
                font-family: Roboto, Arial, sans-serif;
                font-size: 18px;
                color: rgb(0, 68, 255);
                box-shadow: 0 0 8px rgb(0, 68, 255);
            }

            textarea {
                width: calc(100% - 12px);
                padding: 5px;
            }

            .testbox {
                display: flex;
                justify-content: center;
                align-items: center;
                height: inherit;
                padding: 20px;
            }

            form {
                width: 100%;
            
                padding: 20px;
                border-radius: 6px;
                background: #000;
                box-shadow: 0 0 8px rgb(0, 68, 255);
            }



            input,
            select,
            textarea {
                margin-bottom: 10px;
                border: 1px solid #ccc;
                border-radius: 3px;
            }

            input {
                width: calc(100% - 10px);
                padding: 5px;
            }

            input[type="date"] {
                padding: 4px 5px;
            }

            textarea {
                width: calc(100% - 12px);
                padding: 5px;
            }

            .item:hover p,
            .item:hover i,
            .question:hover p,
            .question label:hover,
            input:hover::placeholder {
                color: rgb(0, 68, 255);
            }

            .item input:hover,
            .item select:hover,
            .item textarea:hover {
                border: 1px solid transparent;
                box-shadow: 0 0 3px 0 rgb(0, 68, 255);
                color: rgb(0, 68, 255);
            }

            .item {
                position: relative;
                margin: 10px 0;
            }

            .item span {
                color: red;
            }

            input[type="date"]::-webkit-inner-spin-button {
                display: none;
            }

            .item i,
            input[type="date"]::-webkit-calendar-picker-indicator {
                position: absolute;
                font-size: 20px;
                color: black;
            }

            .item i {
                right: 1%;
                top: 30px;
                z-index: 1;
            }

            .week {
                display: flex;
                justify-content: space-between;
            }

            .columns {
                display: flex;
                justify-content: space-between;
                flex-direction: row;
                flex-wrap: wrap;
            }

            .columns div {
                width: 228%;
            }

            [type="date"]::-webkit-calendar-picker-indicator {
                right: 1%;
                z-index: 2;
                opacity: 0;
                cursor: pointer;
            }

            input[type=radio],
            input[type=checkbox] {
                display: none;
            }

            label.radio {
                position: relative;
                display: inline-block;
                margin: 5px 20px 15px 0;
                cursor: pointer;
            }

            .question span {
                margin-left: 30px;
            }

            .question-answer label {
                display: block;
            }

            label.radio:before {
                content: "";
                position: absolute;
                left: 0;
                width: 17px;
                height: 17px;
                border-radius: 50%;
                border: 2px solid #ccc;
            }

            input[type=radio]:checked+label:before,
            label.radio:hover:before {
                border: 2px solid rgb(0, 68, 255);
            }

            label.radio:after {
                content: "";
                position: absolute;
                top: 6px;
                left: 5px;
                width: 8px;
                height: 4px;
                border: 3px solid #006622;
                border-top: none;
                border-right: none;
                transform: rotate(-45deg);
                opacity: 0;
            }

            input[type=radio]:checked+label:after {
                opacity: 1;
            }

            .flax {
                display: flex;
                justify-content: space-around;
            }

            .btn-block {
                margin-top: 10px;
                text-align: center;
            }


            @media (min-width: 568px) {

                .name-item,
                .city-item {
                    display: flex;
                    flex-wrap: wrap;
                    justify-content: space-between;
                }

                .name-item input,
                .name-item div {
                    width: calc(50% - 20px);
                }

                .name-item div input {
                    width: 97%;
                }

                .name-item div label {
                    display: block;
                    padding-bottom: 5px;
                }
            }
        </style>
    </head>

    <body>
        <div class="testbox">


            <form align="center">
                <div class="banner">
                    <aside> <img class="demo" src="https://i.ibb.co/ws5rF2w/SEDIAL.png" width="200" height="80"></aside>

                

                </div>
                <br />
                <fieldset>
                    <legend>Detalle</legend>

                    <div align="center">

                    <div class="form-group">
                        <label class="item"><strong>Token Firma Digital: </strong>"""+str(llave)+"""</label>
                        <p>----------------------------------------------------</p>
                        </div>

                    <div class="form-group">
                        <label class="item"><strong>PASO 1:</strong></label>
                        <p>Descargar e imprimir el formato adjunto al correo</p>
                        </div>

                        <div class="form-group">
                        <label class="item"><strong>PASO 2:</strong></label>
                        <p>Llenar los campos requeridos del documento (Firma del testigo es quien te acompaño durante el registro)</p>
                        </div>

                        <div class="form-group">
                        <label class="item"><strong>PASO 3:</strong></label>
                        <p>Escanear el documento</p>
                        </div>

                        <div class="form-group">
                        <label class="item"><strong>PASO 4:</strong></label>
                        <p>Copiar la siguiente llave para el cargue del archivo: """+str(tiquete)+"""</p>
                        </div>
                        
                    <div class="form-group">
                        <label class="item"><strong>PASO 5:</strong></label>
                        <p>Ingresar al siguiente <a href="https://vernal-acrobat-301119.uc.r.appspot.com/carga_procedimiento_firmadigital_firmado">link</a> para subir el archivo escaneado</p>
                        </div>
                        
                    
                <p>--------------------------------------------------------------------------------------</p>
                <p><strong>*DECIMOSEXTA: FIRMA DIGITAL.-*</strong></p>
                <p>Para toda la documentación interna de la empresa, se utilizará una firma digital, la cual tendrá la misma validez que la firma caligráfica para todos los efectos internos y legales, incluyendo pero no limitándose a:</p>
                <p><strong>1. </strong>Recibo de documentación.</p>
                <p><strong>2. </strong>Firma de Otrosí al contrato laboral.</p>
                <p><strong>3. </strong>Firma de recibido de evaluaciones de desempeño.</p>
                <p><strong>4. </strong>Firma de procesos disciplinarios.</p>
                <p></p>
                <p>El empleado con la firma del presente documento declara que entiende y reconoce lo siguiente:</p>
                <p><strong>1. </strong>La firma digital podrá ser utilizada únicamente con el token que le será entregado por parte de la empresa mediante correo electrónico dirigido a la dirección que el empleado registre en los formularios FR-GH-002 “Ficha Básica” y FR-SF-012 “Actualización de Datos”.</p>
                <p><strong>2. </strong>El uso del token es personal e intransferible.</p>
                <p><strong>3. </strong>El empleado es el único responsable de la custodia y cuidado del token.</p>
                <p><strong>4. </strong>En virtud de lo anterior cualquier documento que esté firmado en el sistema Dashboard Sedial, se entiende firmado por el empleado.</p>
        
    </div>
                </fieldset>
    <div class="btn-block">

               
            </div>
            </form>
        </div>
            

    </body>

    </html>



        """
            msg = MIMEMultipart("alternative", None, [MIMEText(text), MIMEText(html,'html')])
            part1 = MIMEText(text, "plain")
            part2 = MIMEText(html, "html")
            msg.attach(part1)
            msg.attach(part2)
                    

        
                        
            msg['From'] = from_addr
            #msg['To'] = ", ".join(to_addr)
            msg['To'] = to_addr 
            msg['Subject'] = subject
            file_name_final = 'FR-GH-084_REGISTRO_FIRMA_DIGITAL_'+str(cc)+'_'+str(dateTimeObj)+'.pdf'

            with open(file_name, 'rb') as f:
                attachment = MIMEApplication(f.read(), Name=file_name_final)
                attachment['Content-Disposition'] = 'attachment; file_name="{}"'.format(file_name_final)

                        
            msg.attach(attachment)
            context = ssl.create_default_context()
            server = smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context)
            server.login(from_addr,password)
            server.send_message(msg, from_addr, to_addr)


            time.sleep(1)

            

            gcs = storage.Client()
            bucket = gcs.get_bucket("<buckename>")
            
            old_file = os.path.join(pathe, fileid+".pdf")
            newfilename = 'FR-GH-084_REGISTRO_FIRMA_DIGITAL_'+str(cc)+'_'+str(dateTimeObj)+'.pdf'
            new_file = os.path.join(pathe, newfilename)
            os.rename(old_file, new_file)   

            blob = bucket.blob("firmas_digitales/"+str(cc)+"/"+newfilename)
            blob.upload_from_filename(
                    os.path.join(pathe, newfilename)
                )    

            mycursor.execute(<sql sentence>)    


            cnx.commit()

            #execute deleteemail function to avoid me have access to raw token
            deletesubject = "Detalle Registro Firmal Digital"
            deleteemail(deletesubject) 

            return redirect(url_for('registro_firma_digital'))
        return render_template('registro_firma_digital.html')
    else:
        return redirect(url_for('login'))
except Exception as e:
    if 'Duplicate entry' in str(e):
        return render_template('cc_firma_presente.html', cc=cc)
    else:    
        return str(e)
finally:
    cnx.close()
    cnx2.close()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文