[GO] J'ai essayé de rendre possible l'envoi automatique d'un e-mail en double-cliquant simplement sur l'icône [GAS / Python]

Synopsis

C'est gênant car le travail d'envoi de courrier est constant. J'ai décidé de l'automatiser.

Pour l'automatisation, nous avons décidé d'en créer un qui répond aux exigences suivantes.

    1. Je souhaite que le déclencheur d'envoi clique sur l'icône du bureau au lieu de la minuterie, etc.
  1. Je souhaite joindre automatiquement un fichier spécifique
    1. Je souhaite me connecter uniquement lors de l'envoi d'un e-mail et me déconnecter immédiatement après l'envoi

Par conséquent, GAS (Google Apps Script) semble être pratique et je n'ai aucune expérience de son utilisation. J'ai décidé de créer un outil avec GAS qui répond aux exigences ci-dessus.

Tout d'abord, j'ai examiné si les trois exigences ci-dessus étaient réellement réalisées.

Condition 1: je veux que le déclencheur d'envoi soit un clic tel qu'une icône de bureau au lieu d'un minuteur

Dans la mesure où j'ai réellement essayé et étudié un peu GAS, malheureusement, le déclencheur d'exécution de GAS est Il ne semblait y avoir que ce qui suit.

① À partir de la feuille de calcul ② Axé sur le temps ③ Depuis le calendrier

Parmi ceux-ci, ① Si vous vérifiez les détails des paramètres de déclenchement dans la feuille de calcul

・ Au démarrage ・ Lors de l'édition ・ Au moment du changement ・ Lors de la soumission d'un formulaire

Il y a, n'est-il pas possible d'utiliser "au démarrage" comme déclencheur? j'ai pensé Déclenché en ouvrant une feuille de calcul et en essayant d'envoyer un e-mail Je l'ai inventé.

Ainsi, en ouvrant une feuille de calcul avec GAS dans Selenium de Python, J'ai décidé de l'utiliser comme déclencheur.

... je pense qu'il pourrait y avoir un moyen plus simple et plus simple, Déclencher un lancement de feuille de calcul ne semble rien faire de mal, Il y a aussi le but d'utiliser un GAZ inexpérimenté, alors j'ai décidé d'aller avec ça.

J'ai téléchargé le pilote chrome requis pour exécuter Selenium à partir de la page suivante. https://sites.google.com/a/chromium.org/chromedriver/downloads

Condition 2: je souhaite joindre automatiquement un fichier spécifique

Cela s'est avéré étonnamment difficile à faire avec GAS.

Car, tant que la feuille de calcul existe sur le serveur, le script GAS semble également être exécuté côté serveur, et il semble qu'il soit difficile de faire fonctionner le fichier sur le PC local qui est le client.

Pour cette raison, par exemple, je savais comment lire un fichier CSV ou texte local, puis extraire les informations décrites dans ces fichiers, mais je ne savais pas comment joindre le fichier local dans ce format de fichier.

En revanche, il semble facile de joindre des fichiers côté serveur, comme Google Drive.

Par conséquent, j'ai décidé de télécharger le fichier local que je souhaite joindre à Google Drive et de le joindre. C'est un peu déroutant car il passe par Google Drive une fois, mais s'il n'y a pas de problèmes de fonctionnement, c'est OK.

Pour le téléchargement sur Google Drive, PyDrive de Python semble être pratique, j'ai donc décidé de l'accepter.

J'ai d'abord pensé à utiliser GAS, mais encore Python. ..

Condition 3: Je souhaite me connecter uniquement lors de l'envoi d'un e-mail et me déconnecter immédiatement après l'envoi

Puisque GAS est exécuté côté serveur, il est difficile d'exploiter l'environnement local ainsi que le fichier local, et comme Python est impliqué dans les exigences 1 et 2 ci-dessus, j'ai pensé que l'exigence 3 serait également implémentée en Python. J'ai pensé à la légère qu'il n'y avait qu'un package qui pouvait facilement connecter / déconnecter le Wi-Fi, mais malheureusement je ne l'ai pas trouvé.

Cependant, j'ai trouvé que PowserShell facilite l'utilisation du Wi-Fi et que les scripts PowerShell peuvent également être facilement appelés du côté Python, j'ai donc décidé d'effectuer une opération Wi-Fi avec PowerShell.

Flux d'outils d'automatisation

J'ai trouvé que les exigences 1 à 3 étaient toutes réalisées, mais les moyens pour les réaliser devenaient un peu compliqués, j'ai donc décidé de les organiser une fois.

キャプチャ.JPG

La première moitié au milieu du processus est comme déjà mentionné, mais le problème est la seconde moitié. Idéalement, lorsque GAS est démarré et qu'un e-mail est envoyé, l'accusé de réception est envoyé à Python en cours d'exécution localement, et à ce moment, un script PowerShell pour déconnecter le Wi-Fi est appelé pour le mettre hors ligne et terminer. Cependant, comme d'habitude, il est difficile de faire le lien avec l'environnement local, nous avons donc décidé de le traiter ci-dessous.

    1. Après avoir atteint l'URL de la feuille de calcul côté Python, accédez à la boîte de réception Gmail toutes les secondes environ et vérifiez si le courrier envoyé automatiquement est arrivé.
  1. S'il arrive, la boîte de dialogue "Envoyer terminé" s'affiche du côté Python.
    1. Si le courrier envoyé automatiquement n'arrive pas dans un certain laps de temps (environ 30 secondes?) Après avoir frappé l'URL de la feuille de calcul, la boîte de dialogue «Échec de l'envoi» s'affiche du côté Python.

Avec les mesures ci-dessus, l'utilisateur pourra connaître le succès / l'échec de la transmission du courrier.

Lorsque cela se produit, je me demande s'il est correct d'utiliser Python pour tout ... mais l'un des objectifs de ce cas est "d'essayer d'utiliser un GAS que je n'ai jamais utilisé", afin que cela puisse être réalisé avec GAS. J'irai avec GAS pour la partie.

Autre / conception détaillée

C'est solitaire que la feuille de calcul qui s'ouvre comme déclencheur pour démarrer GAS n'a vraiment aucun rôle autre qu'un simple déclencheur, et j'ai décidé qu'il n'était pas bon de coder en dur l'adresse de destination lorsque le nombre de destinations de courrier augmentera à l'avenir. J'ai décidé de lister les adresses de livraison dans la feuille de calcul.

ss.JPG

Comme le montre la figure, écrivez dans l'ordre de la cellule A1 vers le bas.

Résultats de la mise en œuvre

Placez le script Python et le script PowerShell créés à l'endroit approprié, écrivez GAS comme décrit ci-dessus, définissez le déclencheur, activez l'API GoogleDrive, placez le raccourci .py sur le bureau et appuyez dessus pour envoyer automatiquement un e-mail Vous pouvez envoyer. Pour référence, les résultats de la mise en œuvre sont les suivants.

cp.png

La source

    1. Python: partie principale

auto_mail_tool.py


import os
import time
import email
import imaplib
import datetime
import chromedriver_binary
from selenium import webdriver
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from selenium.webdriver.chrome.options import Options

#Définir l'adresse et le mot de passe du compte Google
address = 'adresse mail'
pw = 'mot de passe'


#Ouvrez la feuille de calcul, lancez le gaz et envoyez un e-mail
def generate_gas_script():

    print('Envoi d'un e-mail ...')

    #Lancement sans tête du navigateur(Affichage en arrière-plan)Paramètres pour
    option = Options()  #Options disponibles
    option.add_argument('--headless')  #Donner le réglage du mode sans tête
    option.add_argument('--lang=ja-JP')

    #Ouvrez le navigateur pour fonctionner
    drv = webdriver.Chrome(options=option)
    time.sleep(3)

    #Ouvrez la page pour opérer
    drv.get("URL de la feuille de calcul que vous souhaitez ouvrir")

    #Entrez l'adresse dans la barre d'adresse
    drv.find_element_by_id('Email').send_keys(address)
    time.sleep(3)

    #Cliquez sur le bouton "Suivant"
    drv.find_element_by_id('next').click()
    time.sleep(3)

    #Entrer le mot de passe
    drv.find_element_by_id('password').send_keys(pw)
    time.sleep(3)

    #Cliquez sur le bouton "Suivant"
    drv.find_element_by_id('submit').click()
    time.sleep(5)

    drv.quit()  #La feuille de calcul aurait dû s'ouvrir, alors fermez le navigateur


#Connectez-vous au wifi/Déconnecter
def wifi(mode):

    if mode == 'connect':  #Connectez-vous au wifi du SSID spécifié (le SSID lui-même est défini dans PowerShell)
        os.system('powershell -Command' + ' ' + \
                  'powershell -ExecutionPolicy RemoteSigned .\\wifi_on.ps1')

        time.sleep(5)

    elif mode == 'disconnect':  #Se déconnecter du wifi connecté

        os.system('powershell -Command' + ' ' + \
                  'powershell -ExecutionPolicy RemoteSigned .\\wifi_off.ps1')


#Téléchargez le fichier que vous souhaitez joindre au courrier sortant sur Google Drive
def up_file_on_drive():

    #Définissez le chemin et le nom du fichier où se trouve le fichier à télécharger
    tgtfolder = 'Le chemin où se trouve le fichier que vous souhaitez joindre'
    tgtfile = 'Le nom du fichier que vous souhaitez joindre'
    dlttgt = 'title = ' + '"' + tgtfile + '"'  #Utilisé pour obtenir l'ID de fichier

    #Processus d'authentification pour l'utilisation de l'API Google Drive
    gauth = GoogleAuth()
    drive = GoogleDrive(gauth)

    #Si un fichier du même nom est déjà stocké, supprimez-le
    file_id = drive.ListFile({'q': dlttgt}).GetList()[0]['id']
    f = drive.CreateFile({'id': file_id})
    f.Delete()

    time.sleep(3)

    #Téléverser un fichier
    folder_id = 'ID de stockage de fichiers Google Drive'
    f = drive.CreateFile({'title': tgtfile,
                         'mimeType': 'excel/xlsx',
                         'parents': [{'kind': 'drive#fileLink', 'id':folder_id}]})
    f.SetContentFile(tgtfolder + tgtfile)
    f.Upload()

    time.sleep(3)


#Vérifiez si l'e-mail a été envoyé
def confirm_mail_sent():

    tgtac = imaplib.IMAP4_SSL('imap.gmail.com', 993)  #gmail Nom d'hôte du serveur de courrier entrant (IMAP) et numéro de port de réception du courrier utilisant SSL
    tgtac.login(address, pw)

    waitsec = 30  #Délai d'expiration de la logique de confirmation de la transmission du courrier[sec]

    tgtmail = 'Envoyer "Objet du courrier" défini du côté GAS' + get_today()

    #Vérifiez à partir du dernier courrier toutes les secondes pour voir si le courrier envoyé automatiquement est reçu
    for i in range(waitsec, 0, -1):

        title = get_latest_mail_title(tgtac)  #Obtenez l'objet du dernier e-mail

        time.sleep(1)  #1 boucle 1 seconde

        if title == tgtmail:  #Si l'objet du dernier e-mail est celui d'un e-mail envoyé automatiquement
            print('\n La transmission automatique du courrier est terminée.\n')
            return

    #Si le délai de confirmation expire
    print('\n Échec de l'envoi automatique du courrier.\n')


#Obtenez l'objet du dernier e-mail
def get_latest_mail_title(mail):

    mail.select('inbox')  #Sélection de la boîte aux lettres
    data = mail.search(None, 'ALL')[1]  #Récupérez toutes les données de votre boîte mail
    tgt = data[0].split()[-1]  #Recevez la dernière commande par correspondance
    x = mail.fetch(tgt, 'RFC822')[1]  #Obtenir des informations par e-mail (spécifier une norme pouvant être lue par Gmail)
    ms = email.message_from_string(x[0][1].decode('iso-2022-jp'))  #Perspective et obtenir

    sb = email.header.decode_header(ms.get('Subject'))
    ms_code = sb[0][1]  #Acquisition de code de caractère

    #Obtenez uniquement l'objet du dernier e-mail
    if ms_code != None:
        mtitle = sb[0][0].decode(ms_code)
    else:
        mtitle = sb[0][0]

    return mtitle


#Obtenez la date du jour
def get_today():

    now = datetime.date.today()
    tdy = str(now.year) + '/' + str(now.month) + '/' + str(now.day)  #Affichage par date
    wknum = now.weekday()  #Obtenez le numéro du jour du jour (0:Mois... 6:Journée)
    wk = get_now_weekday(wknum)  #Obtenez le jour d'aujourd'hui

    return tdy + '(' + wk + ')'


#Obtenez le jour d'aujourd'hui
def get_now_weekday(key):

    wkdict = {0: 'Mois', 1: 'Feu', 2: 'eau', 3: 'bois', 4: 'Argent', 5: 'sol', 6: 'journée'}
    return(wkdict[key])


if __name__ == '__main__':

    wifi('connect')        # 1.Wi du SSID spécifié-Connectez Fi
    up_file_on_drive()     # 2.Téléchargez le fichier que vous souhaitez joindre à Google Drive
    generate_gas_script()  # 3.Ouvrez la feuille de calcul et lancez GAS
    confirm_mail_sent()    # 4.Vérifiez si l'e-mail envoyé par GAS est bien arrivé
    wifi('disconnect')     # 5.Déconnecter le wifi

    os.system('PAUSE')     #Arrêtez la console

  1. GAS: partie d'envoi d'e-mails

sending_email.gs


function mail_send() {
      
  //Définir les informations de messagerie
  var recip = get_recipient(); //Obtenez l'adresse e-mail du destinataire (répertoriée dans la feuille de calcul)
  var subject  = 'Sujet du courriel:' + get_nowdate(); 
  var yourname = 'À vous tous';
  var myname   = '○○ charge';
  var body = yourname + '\n\n' + myname + 'est.\n\n' + 'Je vous enverrai ○○ aujourd'hui.\n\Merci pour n ou plus.'
  var filename = 'Le nom du fichier que vous souhaitez joindre';
  var foldername = 'test'
  var tgtfile = DriveApp.getFilesByName(filename).next();
  const options = {name: '○○ charge', attachments:[tgtfile]};
    
  //envoyer un e-mail
  GmailApp.sendEmail(recip, subject, body, options);
}

//Obtenez l'adresse e-mail de destination sur la feuille de calcul
function get_recipient(){
  //Définir la feuille cible pour la feuille de calcul
  var spdsht = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spdsht.getActiveSheet();
  
  //Obtenez l'adresse indiquée sur la première ligne
  var tgtcell = sheet.getRange('A1');
  var rcps = tgtcell.getValue();
  var tgtval = rcps;
  
  //Obtenez l'adresse décrite dans la deuxième ligne et les suivantes
  for (let i = 2; tgtval != ''; i++)
  {
    tgtcell = sheet.getRange('A' + i);
    tgtval = tgtcell.getValue();
   
    rcps = rcps + ', ' + tgtval;
  }
    
  return rcps;
//  console.log(rcps) //déboguer
}

//Obtenir la date du jour (y compris le jour)
function get_nowdate()
{
  var da = new Date();

  //Obtenez la date du jour
  var y = da.getFullYear();
  var m = da.getMonth() + 1;  //La lune-Pour obtenir une valeur de 1
  var d = da.getDate();
  
  //Obtenez le jour d'aujourd'hui
  var downum = da.getDay(); //Obtenez le numéro du jour
  var downow = ['journée', 'Mois', 'Feu', 'eau', 'bois', 'Argent', 'sol'][downum]; // 曜journée番号に対応する曜journéeを選択

  return y + '/' + m + '/' + d + '(' + downow + ')';
}
    1. PowerShell: pour la connexion / déconnexion Wi-Fi

3-1. Lors de la connexion

wifi_on.ps1


netsh wlan connect name="Wi-fi que vous souhaitez connecter-SSID Fi"

3-2. Lors de la déconnexion

wifi_off.ps1


netsh wlan disconnect

Remarques: si vous souhaitez appeler .py depuis MATLAB

Écrivez ce qui suit en .m à l'aide de la fonction système.

system('Envie de courir.chemin py')

Autre / pensée

-Le processus d'ouverture du navigateur pour ouvrir la feuille de calcul avec Selenium se fait sans tête, Pour une raison quelconque, quand je l'ai commencé sans tête, un écran différent était affiché par rapport à quand il ne l'était pas, et j'ai un peu souffert. (Le fait que l'écran soit différent a été découvert par capture d'écran avec save_screenshot)   Après tout, ce qui précède est le résultat de la division sur différents écrans.

Référence: https://teratail.com/questions/276976

・ Je me demande si GAS n'a pas de fonction équivalente au mode interactif de Python. .. Je pense que ce serait très pratique s'il y en avait un.

Informations qui ont servi de référence

En particulier, j'étais redevable aux sites suivants. Merci beaucoup.

Contenu Lier la destination
Envoyer un courrier par GAS https://tonari-it.com/gas-gmail-sendemail/
Réglage du déclencheur d'exécution GAS https://takakisan.com/gas-trigger-introduction/
Obtenez la date et le jour avec GAS http://www.googleappsscript.info/2017-07-27/get_now.html
Accéder aux feuilles de calcul avec GAS https://qiita.com/negito6/items/c64a7a8589faaffcfdcf
Joindre un fichier lors de l'envoi d'un e-mail avec GAS https://qiita.com/tanaike/items/94c263d3906ee23ad522 https://news.mynavi.jp/article/gas-11/
GAS+Importer des fichiers sur Google Drive avec HTML https://officeforest.org/wp/2018/12/30/google-apps-script%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%80%E3%82%92%E4%BD%9C%E3%82%8B/ https://tonari-it.com/gas-web-app-google-script-run/ https://www.pre-practice.net/2018/01/google-drive.html
Télécharger des fichiers sur Google Drive avec PyDrive https://note.nkmk.me/python-pydrive-download-upload-delete/ https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e
Script PowerShell de Python (.ps1) appel https://tkstock.site/2019/10/07/python-powershell-shellscript-activate/
Connexion / déconnexion au wifi par PowerShell https://qiita.com/mindwood/items/22e0895473578c4e0c7e http://wgg.hatenablog.jp/entry/20161111/1478846489
Supprimer des fichiers sur Google Drive https://note.nkmk.me/python-pydrive-download-upload-delete/
Obtenez des informations sur les e-mails entrants Gmail avec imaplib https://py.minitukuc.com/2017/11/07/gmailhonbun/
Masquer la fenêtre racine lors de l'utilisation de la boîte de dialogue Tkinter https://stackoverflow.com/questions/1406145/how-do-i-get-rid-of-python-tkinter-root-window
Comment démarrer Selenium sans tête https://watlab-blog.com/2019/08/18/selenium-chrome-background/ https://qiita.com/memakura/items/20a02161fa7e18d8a693
Capture d'écran pour le débogage du démarrage sans tête Selenium https://qiita.com/orangain/items/6a166a65f5546df72a9d
Gestion des erreurs lors du démarrage de Selenium sans tête https://qiita.com/yukanashi/items/c7e954130029fe708b79

dernier

Nous apprécions vos suggestions, suggestions d'amélioration et suggestions d'erreurs. S'il vous plaît ne pas hésiter. Je suis ravi de gagner à la loterie 100 000 yens.

Recommended Posts

J'ai essayé de rendre possible l'envoi automatique d'un e-mail en double-cliquant simplement sur l'icône [GAS / Python]
J'ai essayé de rendre possible l'envoi automatique d'un e-mail en double-cliquant simplement sur l'icône [Python]
Exportez le rapport au format PDF à partir de DB avec Python et attachez-le automatiquement à un e-mail et envoyez-le
Pour envoyer automatiquement des e-mails avec des pièces jointes à l'aide de l'API Gmail en Python
J'ai essayé d'envoyer automatiquement la littérature du nouveau virus corona à LINE avec Python
Il fait froid, j'ai donc essayé de permettre d'allumer / d'éteindre automatiquement le chauffage AC avec Raspberry Pi!
[Python] Japonais simple ⇒ J'ai essayé de créer un outil de traduction en anglais
J'ai essayé de créer une fonction de similitude d'image avec Python + OpenCV
[Python] J'ai essayé de résumer le type collectif (ensemble) d'une manière facile à comprendre.
Lorsque j'ai essayé d'exécuter Python, j'ai été ignoré dans le Microsoft Store
[Zaif] J'ai essayé de faciliter le commerce de devises virtuelles avec Python
J'ai essayé d'analyser la carte du Nouvel An par moi-même en utilisant python
J'ai essayé de créer un système pour acquérir automatiquement le guide des programmes → l'enregistrer dans le calendrier en un jour
J'ai essayé d'obtenir une image en grattant
Envoyez un email à l'adresse de Spushi avec python
J'ai essayé d'utiliser le module Datetime de Python
J'ai essayé d'envoyer un email avec SendGrid + Python
J'ai fait de mon mieux pour créer une fonction d'optimisation, mais cela n'a pas fonctionné.
[Introduction] J'ai essayé de l'implémenter moi-même tout en expliquant l'arbre de dichotomie
J'ai essayé de faire sonner le téléphone lorsqu'il a été publié sur le poste IoT
Un débutant en python a tenté de faire un stage dans une entreprise informatique [Jour 3 vers les nuages ...]
Les débutants en Python ont créé un chat BOT alors j'ai essayé de résumer comment le faire
[Introduction] J'ai essayé de l'implémenter moi-même tout en expliquant pour comprendre la dichotomie
J'ai essayé de faciliter la modification du paramètre du proxy authentifié sur Jupyter
J'ai essayé de représenter graphiquement les packages installés en Python
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de résoudre Soma Cube avec python
Suite ・ J'ai essayé de créer Slackbot après avoir étudié Python3
J'ai essayé d'implémenter le perceptron artificiel avec python
[Python] J'ai essayé de représenter graphiquement le top 10 des ombres à paupières
J'ai essayé de résoudre le problème avec Python Vol.1
Je souhaite envoyer automatiquement un e-mail de création d'entreprise
J'ai essayé de créer une application OCR avec PySimpleGUI
J'ai essayé de résumer les opérations de chaîne de Python
Django super introduction par les débutants Python! Partie 6 J'ai essayé d'implémenter la fonction de connexion
[Python] J'ai essayé de faire une application qui calcule le salaire en fonction des heures de travail avec tkinter
J'ai essayé de créer une API RESTful en connectant l'API rapide du framework Python explosif à MySQL.
J'ai essayé de faire de la vidéo de diffusion Masami comme IPPON Grand Prix (OpenCV: version Python)
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé de simuler la propagation de l'infection avec Python
J'ai essayé de créer diverses "données factices" avec Python faker
J'ai essayé différentes méthodes pour envoyer du courrier japonais avec Python
J'ai essayé d'envoyer un e-mail d'Amazon SES avec Python
Code pour envoyer du courrier basé sur la liste de diffusion Excel
[Python] J'ai essayé de visualiser la relation de suivi de Twitter
J'ai essayé d'implémenter la fonction d'envoi de courrier en Python
J'ai essayé d'énumérer les différences entre java et python
J'ai fait un chronomètre en utilisant tkinter avec python
J'ai essayé de créer une interface graphique à trois yeux côte à côte avec Python et Tkinter
J'ai essayé de changer le script python de 2.7.11 à 3.6.0 sur Windows10
Un débutant en python a essayé de faire un stage dans une entreprise informatique
J'ai essayé de créer un site qui permet de voir facilement les informations mises à jour d'Azure
J'ai essayé de vérifier l'identification du locuteur par l'API de reconnaissance du locuteur d'Azure Cognitive Services avec Python. # 1
J'ai essayé de vérifier l'identification du locuteur par l'API de reconnaissance du locuteur d'Azure Cognitive Services avec Python. # 2
J'ai essayé de trouver la différence entre A + = B et A = A + B en Python, alors notez
J'ai essayé de résumer le contenu de chaque paquet enregistré par Python pip en une seule ligne