Example #1
0
    def test_send_email_with_required_args(self):
        try:
            gmail_configuration = self.configuration.get_email_apps()[0]
            gmail_app = GmailEmailApp(config=gmail_configuration)

            gmail_app.send_email(subject='test_send_email_with_required_args',
                                 to=[gmail_configuration['email_address']])
        except Exception as e:
            logger.error("Test failed with exception: %s" % e)
            self.fail("Test failed with exception: %s" % e)
Example #2
0
    def test_send_email_with_html(self):
        try:
            gmail_configuration = self.configuration.get_email_apps()[0]
            gmail_app = GmailEmailApp(config=gmail_configuration)

            gmail_app.send_email(subject='test_send_email_with_html',
                                 to=[gmail_configuration['email_address']],
                                 html='<h1>Html only</h1>')
        except Exception as e:
            logger.error("Test failed with exception: %s" % e)
            self.fail("Test failed with exception: %s" % e)
Example #3
0
 def test_connect(self):
     # Test the connection with the correct api key
     try:
         gmail_configuration = self.configuration.get_email_apps()[0]
         GmailEmailApp(config=gmail_configuration)
     except SMTPAuthenticationError as e:
         logger.error('Error connecting with the correct credentials: %s',
                      e)
         self.fail('Error connecting with the correct credentials')
     else:
         logger.info('Connected with the correct credentials successfully.')
     # Test that the connection is failed with the wrong credentials
     with self.assertRaises(SMTPAuthenticationError):
         gmail_wrong_configuration = copy.deepcopy(gmail_configuration)
         gmail_wrong_configuration['api_key'] = 'wrong_key'
         GmailEmailApp(config=gmail_wrong_configuration)
     logger.info(
         "Loading Dropbox with wrong credentials failed successfully.")
Example #4
0
    def test_send_email_with_all_args(self):
        try:
            gmail_configuration = self.configuration.get_email_apps()[0]
            gmail_app = GmailEmailApp(config=gmail_configuration)

            gmail_app.send_email(subject='test_send_email_with_all_args',
                                 to=[gmail_configuration['email_address']],
                                 cc=[gmail_configuration['email_address']],
                                 bcc=[gmail_configuration['email_address']],
                                 text='Test plain/text body',
                                 html='<h1>Test html body</h1>',
                                 attachments=[
                                     os.path.join(self.test_data_path,
                                                  'sample_data.txt')
                                 ],
                                 sender=gmail_configuration['email_address'],
                                 reply_to=gmail_configuration['email_address'])
        except Exception as e:
            logger.error("Test failed with exception: %s" % e)
            self.fail("Test failed with exception: %s" % e)
Example #5
0
def main():
    """
    :Example:
    python main.py [-m crawl_and_send]
                   -c confs/template_conf.yml
                   -l logs/output.log
    """

    # Initializing
    args, configuration = init_main()

    # Start in the specified mode
    if args.run_mode == 'list_emails':
        data_store = JobBotMySqlDatastore(
            config=configuration.get_datastores()[0])
        show_ads_checked(ads=data_store.get_applications_sent())
    elif args.run_mode == 'remove_email':
        data_store = JobBotMySqlDatastore(
            config=configuration.get_datastores()[0])
        data_store.remove_ad(email_id=args.email_id)
    elif args.run_mode == 'upload_files':
        upload_files_to_cloudstore(cloud_store=JobBotDropboxCloudstore(
            config=configuration.get_cloudstores()[0]))
    elif args.run_mode == 'create_table':
        data_store = JobBotMySqlDatastore(
            config=configuration.get_datastores()[0])
        data_store.create_applications_sent_table()
    elif args.run_mode == 'crawl_and_send':
        crawl_and_send_loop(lookup_url=configuration.lookup_url,
                            check_interval=configuration.check_interval,
                            crawl_interval=configuration.crawl_interval,
                            anchor_class_name=configuration.anchor_class_name,
                            data_store=JobBotMySqlDatastore(
                                config=configuration.get_datastores()[0]),
                            cloud_store=JobBotDropboxCloudstore(
                                config=configuration.get_cloudstores()[0]),
                            email_app=GmailEmailApp(
                                config=configuration.get_email_apps()[0],
                                test_mode=configuration.test_mode))
    else:
        logger.error('Incorrect run_mode specified!')
        raise argparse.ArgumentTypeError('Incorrect run_mode specified!')
Example #6
0
def main():
    """
    :Example:
    python main.py -m run_mode_1
                   -c confs/template_conf.yml
                   -l logs/output.log
    """

    # Initializing
    args = _argparser()
    _setup_log(args.log, args.debug)
    logger.info("Starting in run mode: {0}".format(args.run_mode))
    # Load the configuration
    configuration = Configuration(config_src=args.config_file)
    # Init the Cloudstore
    cloud_store = DropboxCloudstore(config=configuration.get_cloudstores()[0])
    # Init the Datastore
    data_store = MySqlDatastore(**configuration.get_datastores()[0])
    # Init the Email App
    gmail_configuration = configuration.get_email_apps()[0]
    gmail_app = GmailEmailApp(config=configuration.get_email_apps()[0])

    # Mysql examples
    logger.info("\n\nMYSQL EXAMPLE\n-------------------------")
    logger.info("\n\nTables in current DB: {0}".format(
        list(data_store.show_tables())))
    logger.info("Creating Table: orders")
    table_schema = """ order_id INT(6) PRIMARY KEY,
                       order_type VARCHAR(30) NOT NULL,
                       location VARCHAR(30) NOT NULL """
    data_store.create_table(table='orders', schema=table_schema)
    logger.info("Tables in current DB:\n{0}".format(
        list(data_store.show_tables())))
    logger.info("Inserting into orders the values:\n(1 simple newyork)..")
    insert_data = {
        "order_id": 1,
        "order_type": "plain",
        "location": "new_york"
    }
    data_store.insert_into_table(table='orders', data=insert_data)
    logger.info("SELECT * FROM orders;\n{0}".format(
        data_store.select_from_table(table='orders')))
    logger.info("Deleting the inserted row from table orders..")
    data_store.delete_from_table(table='orders', where='order_id=1')
    logger.info("SELECT * FROM orders;\n{0}".format(
        data_store.select_from_table(table='orders')))
    logger.info("Dropping Table: orders")
    data_store.drop_table(table='orders')
    logger.info("Tables in current DB:\n{0}".format(
        list(data_store.show_tables())))

    # Dropbox examples
    logger.info("\n\nDROPBOX EXAMPLE\n-------------------------")
    logger.info("List of files in Dropbox /python_template:\n{0}".format(
        list(cloud_store.ls(path='/python_template').keys())))
    upload_path = "/python_template/file1.txt"
    file_content = "test file content"
    logger.info("Uploading file {file} with content:\n{content}".format(
        file=upload_path, content=file_content))
    cloud_store.upload_file(file_bytes=file_content.encode(),
                            upload_path=upload_path)
    logger.info("List of files in Dropbox /python_template:\n{0}".format(
        list(cloud_store.ls(path='/python_template').keys())))
    downloaded_file = cloud_store.download_file(frompath=upload_path)
    logger.info(
        "Downloaded file and its content is:\n{0}".format(downloaded_file))
    cloud_store.delete_file(file_path=upload_path)
    logger.info("Deleting file {file}..".format(file=upload_path))
    logger.info("List of files in Dropbox /python_template:\n{0}".format(
        list(cloud_store.ls(path='/python_template').keys())))

    # Gmail examples
    logger.info("\n\nGMAIL EXAMPLE\n-------------------------")
    subject = "Email example"
    body = "<h1>This is an html body example</h1><br><b>This goes to the html argument. " \
           "You can use the text argument for plain text.</b>"
    emails_list = [gmail_configuration['email_address']]
    attachments_paths = [os.path.join('data', 'sample_data.txt')]
    logger.info(
        "Sending email with `subject` = `{subject}`, `from,to,cc,bcc,reply_to` = `{email_addr}`, "
        "`html` = `{body}` and `attachments` = `{attachments}`".format(
            subject=subject,
            email_addr=emails_list[0],
            body=body,
            attachments=attachments_paths))
    gmail_app.send_email(subject=subject,
                         to=emails_list,
                         cc=emails_list,
                         bcc=emails_list,
                         html=body,
                         attachments=attachments_paths,
                         sender=emails_list[0],
                         reply_to=emails_list[0])
Example #7
0
 def test_is_connected_and_exit(self):
     gmail_configuration = self.configuration.get_email_apps()[0]
     gmail_app = GmailEmailApp(config=gmail_configuration)
     self.assertEqual(True, gmail_app.is_connected())
     gmail_app.__exit__()
     self.assertEqual(False, gmail_app.is_connected())
Example #8
0
def crawl_and_send_loop(lookup_url: str, check_interval: int,
                        crawl_interval: int, anchor_class_name: str,
                        data_store: JobBotMySqlDatastore,
                        cloud_store: JobBotDropboxCloudstore,
                        email_app: GmailEmailApp) -> None:
    """
    The main loop.
    Crawls the ad site for new ads and sends emails where applicable and informs the applicant.

    :params lookup_url:
    :params check_interval:
    :params data_store:
    :params cloud_store:
    :params gmail_app:
    """

    ad_site_crawler = XeGrAdSiteCrawler(
        stop_words=cloud_store.get_stop_words_data(),
        anchor_class_name=anchor_class_name)
    attachments_local_paths = [
        os.path.join(cloud_store.local_files_folder, attachment_name)
        for attachment_name in cloud_store.attachments_names
    ]
    # Get the email_data, the attachments and the stop_words list from the cloudstore
    cloud_store.download_attachments()
    application_to_send_subject, application_to_send_html = cloud_store.get_application_to_send_email_data(
    )
    inform_should_call_subject, inform_should_call_html = cloud_store.get_inform_should_call_email_data(
    )
    inform_success_subject, inform_success_html = cloud_store.get_inform_success_email_data(
    )

    links_checked = [
        row[0] for row in data_store.get_applications_sent(columns='link')
    ]
    logger.info("Waiting for new ads..")
    while True:
        new_ads = list(
            ad_site_crawler.get_new_ads(lookup_url=lookup_url,
                                        ads_checked=links_checked,
                                        crawl_interval=crawl_interval))

        if len(new_ads) > 0:
            links_checked = [
                row[0]
                for row in data_store.get_applications_sent(columns='link')
            ]
            emails_checked = [
                row[0]
                for row in data_store.get_applications_sent(columns='email')
            ]
            for link, email in new_ads:
                if link not in links_checked and (email not in emails_checked
                                                  or email is None):
                    if email is None:
                        # Email applicant to inform him that he should call manually
                        logger.info(
                            "Link ({}) has no email. Inform the applicant.".
                            format(link))
                        email_app.send_email(
                            subject=inform_should_call_subject,
                            html=inform_should_call_html.format(link=link),
                            to=[email_app.get_self_email()])
                    else:
                        # Send application after 1 minute (don't be too cocky)
                        time.sleep(60)
                        logger.info("Sending email to: {}. Ad Link: {}".format(
                            email, link))
                        email_app.send_email(
                            subject=application_to_send_subject,
                            html=application_to_send_html.format(link),
                            to=[email],
                            attachments=attachments_local_paths)

                        # Inform applicant that an application has been sent successfully
                        email_app.send_email(subject=inform_success_subject,
                                             html=inform_success_html.format(
                                                 email=email, link=link),
                                             to=[email_app.get_self_email()])

                    email_info = {
                        "link": link,
                        "email": email,
                        "sent_on": datetime.datetime.utcnow().isoformat()
                    }
                    data_store.save_sent_application(email_info)
                    logger.info("Waiting for new ads..")

        # Look for new ads every 2 minutes
        logger.debug("Sleeping for {check_interval} seconds..".format(
            check_interval=check_interval))
        time.sleep(check_interval)