CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • Google Summer of Code »
  • Email Preview Cluster
Pages: 1 [2] 3

Author Topic: Email Preview Cluster  (Read 5384 times)

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
May 21, 2015, 10:30:54 pm
Had a skype chat with Tim yesterday.
We discussed how the Three agent system (Composer, Manager, Renderer) would be beneficial over a Two agent system (Composer, Manager+Renderer):
Easier to Scale out. More Renderers and Less Managers would be required. Will need different managers for webmail and non-webmail clients.
We discussed what will be the requests and responses made between each of these three agents.
We also discussed how we can code the "From address" of every test mail that'll be sent so that each test mail could uniquely be identified by the bot.
I'll be doing doing the following things over the next few days:
* Writing a webdriver script that'll send an email to a Gmail account.
* Exploring the CiviMail codebase.

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
May 25, 2015, 02:29:00 pm
Found a set of shell and SMTP commands(see below) you can use to send a mail, but not sure how to make a shell script out of them because the SMTP commands that are executed after the connection with smtp.gmail.com has been made can't be executed using a shell script (see pictures).
Code: [Select]
$ openssl s_client -connect smtp.gmail.com:465 -crlf -ign_eof
...............

         ###Server Response
         ###Connection to the server will be established
..............
EHLO localhost
### Server Response
AUTH LOGIN
###Server Response
OpenSSLbase64username
###Server Response
OpenSSLbase64password
###Server Response
MAIL FROM: <abcdabcd@gmail.com>
###Server Response
RCPT TO: <abcd1234@yahoo.com>
###Server Response
DATA
###Server Response
Subject: Test email through smtp.google.ca with openssl
Message body.
.
###Server Response
QUIT

Also, the gmail smtp server overwrites the from address everytime and the mail gets sent from the gmail id that has been used to log in to the gmail server. However this shouldn't be a problem with the CiviCRM mail server, I think. Can we perform tests to ensure that?

And if we can't use a shell script to execute these commands then I should probably try writing a javascript/php script for it. What do you think I should do? Will the already existing codes in CiviMail be of any use here?
Another question, what are we going to do about pictures and other attachments?

By the way, this is the WebdriverIO code that log into a gmail account and takes the screenshot of the first email in the Inbox. I've only learnt to open the first mail for now, I'll learn to open any specific mail in a few days. There's a problem with this code. The waiting times don't prove sufficient sometimes and the program returns with errors. What waiting times do you think we should use?
Code: [Select]
path = require ('path')
webdriverio = require ('webdriverio')
var location
var options = {
    desiredCapabilities: {
        browserName: 'firefox'
    }
};
webdriverio
        .remote(options)
        .init()
        .url ('https://gmail.com')
        .setValue ('input[type="email"]', 'username123')
.click('#next')
.windowHandleMaximize()
.waitFor('input[type="password"]',5000)
        .setValue ('input[type="password"]', 'password123')
        .click ('#signIn')
.waitFor('input[aria-label="Search"]',20000)
.click('#:3w')
.waitFor('img[alt="In new window"]',10000)
.saveScreenshot("test")
.close();

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
May 31, 2015, 03:09:24 am
What I've done till now:
* Setup a ssmtp system on my laptop that enable to send HTML emails through a php script using smtp.gmail.com:587 and my gmail account
* Created a WebdriverIO script that logs into my gmail acount, opens the first email, takes a screenshot and saves it.
Work to do over the next week:
* Integrate these two systems to create a working model which returns a screenshot when fed an HTML code.
For this I first need to:
* Learn to feed the php script the html code from a file or a database (Which one should I choose?)
* View any mail on a gmail inbox using the from email address through WebdriverIO.
* Use an smtp server other than gmail as gmail overwrites the from address. (Which one should I use?)

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Email Preview Cluster
June 02, 2015, 01:27:38 am
I'm impressed that you figured out how to use s_client to establish a secure connection to an SMTP server. It's good to have enough understanding of SMTP that you could send one or two messages by hand.

In practice, of course, one wouldn't want to use that technique on a day-to-day basis for writing code -- most programming languages have a library which can handle that. In NodeJS, the "Nodemailer" library seems like a good option -- http://www.nodemailer.com/ .

Quote
And if we can't use a shell script to execute these commands then I should probably try writing a javascript/php script for it. What do you think I should do? Will the already existing codes in CiviMail be of any use here?

I would strongly vote for JS. The code which sends the test mailing over SMTP should be part of the "Renderer". Since the "Renderer" (and "Manager") are already using NodeJS for other reasons, it's more consistent to also implement this in NodeJS.

There were a couple strong/debatable assertions in there, so I'll try to defend those with arguments:

Assertion 1. The code which sends the test mailing over SMTP should be part of the "Renderer"

I've added a section at the bottom of the wiki about delivering test messages.

http://wiki.civicrm.org/confluence/display/CRM/Email+Preview+Infrastructure

Assertion 2. The Manager and Webmail Renderer should be internally consistent -- using one language (JS/NodeJS)

We have three components -- the Composer, Manager, and Renderer. CiviMail already has a composer UI (written in PHP+AngularJS), and there are a number of other open-source email projects which have composer UIs (written in PHP or Python or Ruby or JS or C# or Java). However, the Manager+Renderer components are pretty novel (ie no known open-source implementations). I think they can be useful for Civi and for other open-source projects, but that means they should be designed as essentially standalone components. As standalone components, it's best if they're "internally consistent" and focus one language because:

  • One language makes it easier to attract other contributors. (A prospective contributor only needs to understand Javascript.)
  • One language only requires one dependency-management tool. If a sysadmin or developer wants to download our stuff along with dependencies, he runs one command "npm install". (Rather than two commands, "npm install" and "composer install".)

Quote
Another question, what are we going to do about pictures and other attachments?

We'll have to change the protocol. There are two possible changes, either:

a) Add fields for passing the list of attachments.

b) Instead of passing separate JSON fields for "subject", "body_text", and "body_html", we could pass one big field that contains the fully-rendered email message.

We will need to deal with these, but for the moment I think we should defer and first get a full process working using the simplified model (subject/body_text/body_html).

Perhaps you could add a section to http://wiki.civicrm.org/confluence/display/CRM/Email+Preview+Infrastructure which documents general features we still need to tackle?

Quote
The waiting times don't prove sufficient sometimes and the program returns with errors. What waiting times do you think we should use?

Given that personal Internet connectivity can be flaky, I think it's OK to go as high as 30-60 seconds. However, if it's consistently taking longer than 30 seconds, then something is wrong. My guesses (in order of top-guess to worst-guess):

  • The "timeout" error is not really a "timeout" error -- it may be an edge-case that we haven't recognized. For example, maybe gmail.com shows different markup 10% of the time for some reason that we don't know. The only way to identify this would be (a) to modify the code to record a log of all the pages/screens, and then (b) run the script several times, and finally (c) compare the logs to see if gmail.com appears the same each time.
  • The Internet connection is really bad.
  • The activity is getting throttled (by gmail.com, by an ISP, or by some corporate firewall) -- eg If you run 10 tests per minute, and if each test does a login on gmail.com, then the Gmail folks might find that obnoxious. If this is the problem, then we could impose some throttling on ourselves (eg 5 tests minute -- or whatever rates puts us below a threshold that would annoy the upstream folks) or we could optimize our logic (eg only login when NodeJS starts; don't login for each individual test message). However, I wouldn't spend time developing on this until we rule-out the simpler explanations.

Suggested tasks

I think these would be some good steps to build on what you've done so far:

  • Take your current code using WebdriverIO. Extend the code to read all settings (eg the gmail username+password) from a JSON file.
  • Make a git repo for your current code using WebdriverIO. Post it on github.com.
  • Extend the code to also send a test mailing over SMTP (eg with nodemailer).

Ideally, one could run the code using a process like this:

Code: [Select]
## Download the code
$ git clone https://github.com/utkarshsharma/webmail-renderer
$ cd webmail-renderer
$ npm install
## Create a config file
$ cp config.json.template config.json
$ vi config.json   (<== Put in gmail credentials ==>)
## Run the renderer
$ npm main.js

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 03, 2015, 04:49:00 pm
Things I did:
1. Extended the webdriver IO code to read username and password from a json file.
2. Made a git repo https://github.com/utkarshsharma/webmail-renderer

Just follow instructions given the Readme.txt to run this renderer and let me know if it works at all.  :P
This webdriver code is supposed to read your gmail username and password from the config.json file that you'll make and then use it to login to your gmail account, open the first email, take it's screenshot and display it in a new tab. All this, in firefox.

Things to do:
1. Open any email using the webdriverIO script.
2. Extend the code to also send a test mailing over SMTP (eg with nodemailer).

@Tim: I agree with you about attachments. We'll worry about them later.
About the error due to waiting times, I am pretty sure they were due to problems with the internet connection as I am no longer facing any such issue. And when I was testing this script using a faster internet connection, even then there were no problems. But we should still perform the tests that you suggested later during the course of this project to be completely sure.

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 10, 2015, 03:37:16 am
Things I've done so far:
I can now send email using nodemailer from the js script. I can also open any email identified by the unique from address using webdriverio.

Minor problems that need to be addressed now:
1. smtp.gmail.com overwrites from addresses. We need a different smtp server. This is the list of servers that nodemailer supports
https://github.com/andris9/nodemailer-wellknown#supported-services
2. The security of gmail accounts needs to be reduced manually for nodemailer to be able to send emails through them.

A little more on what the Renderer script does now:
The engine that I now have, picks up the email (Subject, Text, HTML) from a json file, picks up the sending gmail account's (with security reduced manually) details from another json file, sends an email from it, then it picks up the receiving gmail account's details from yet another json file, opens it, takes the screenshot and displays it. I haven't yet uploaded it to git though. I'll upload it as soon as you it is approved.

Things to do now:
1. I want to now know what all I should do to make my midterm submission ready.
2. And I also need to start working towards building the composer and the manager. I'll appreciate some guidance on how I can do that.

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Email Preview Cluster
June 10, 2015, 05:30:04 am
OK, that sounds like progress. Could you push the latest changes to Github (and post a comment afterward so that I can check it out)?

Generally, I think these would be good goals for the midterm:

  • Instead of reading the sample email from a local JSON file, read it from a URL (eg "http://localhost/email.json"). The URL should be configurable (config.json / config.json.template).
  • Poll the address periodically (eg once every minute) and run the preview. (For the moment, this may cause it to retest the same message. This is the server's fault, not a problem in webmail-renderer. We'll fix that by providing a better server.)
  • Add support for a second webmail system (eg Yahoo Mail or Hotmail/Live.com/Outlook.com). We don't need to go wild with a dozen systems, but we should make it clear how the code can grow to accommodate more.
  • To simplify the setup/startup, remove the dependency on Selenium. Instead, install phantomjs via npm . When a user runs the program, automatically start phantom ("bin/phantomjs --webdriver=4444"). There's more discussion on https://www.npmjs.com/package/phantomjs under under "Running via node".

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 11, 2015, 11:20:22 pm
The changes including the nodemailer part have been pushed to github.
I haven't yet implemented the 4 points you suggested in your last post.
I have a few doubts regarding them:
Quote
The URL should be configurable (config.json / config.json.template)
I am sorry I didn't understand what you mean by that. Do you mean I should enable write permissions for that file? How do we do that?
Edited
Got it. The URL to the file should be configurable by the user. I'll add another field in the config.json.template for the user to enter path to the email json file.

Quote
Poll the address periodically (eg once every minute) and run the preview.
Is this for the case the message hasn't reached before we start the webdriverio script?
If that is what it meant, I just have to keep looking every minute for the email from the unique email id and not proceed to the code which takes the screenshot, until I can find such an email. Am I correct?
« Last Edit: June 14, 2015, 03:16:34 am by utkarshsharma »

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Email Preview Cluster
June 14, 2015, 07:08:17 am
Quote from: utkarshsharma on June 11, 2015, 11:20:22 pm
The changes including the nodemailer part have been pushed to github.

Cool. A couple small suggestions:

1. There's now two config templates (config.json.template and send_credentials.json.template). For someone installing, it's easier if they only have to copy/edit one template. Perhaps config.json.template could include all the config options, eg

Code: [Select]
{
  "gmail": {"username": "myusername", "password": "mypassword"},
  "send": {"username": "myotherusername", "password": "myotherpassword"}
}

2. The folder "node_modules/nodemailer" should not be committed to git.  Adding this increases the size of the repo by >50x (24k vs 1.8mb). When it comes time to review proposed changes (like the PR which I sent), that extra mass will make for bigger changes (more difficult review). Instead, the idea is to have one small file ("package.json") and let a tool handle downloads for all the dependencies ("npm install"). This also has the benefit of smarter caching. (If, for example, you develop two different projects which both utilize "nodemailer", then "npm install" will only perform the download once.)

Quote from: utkarshsharma on June 11, 2015, 11:20:22 pm
Quote
The URL should be configurable (config.json / config.json.template)
Edited
Got it. The URL to the file should be configurable by the user. I'll add another field in the config.json.template for the user to enter path to the email json file.

Yup, exactly. The idea here is that the URL could point to a local test file (during development) or it could point to the Manager's URL.

Quote from: utkarshsharma on June 11, 2015, 11:20:22 pm
Quote
Poll the address periodically (eg once every minute) and run the preview.
Is this for the case the message hasn't reached before we start the webdriverio script?
If that is what it meant, I just have to keep looking every minute for the email from the unique email id and not proceed to the code which takes the screenshot, until I can find such an email. Am I correct?

That is an important issue which you should manage, but I was thinking about a different issue.

So far during development, the script has rendered exactly one message. However, over time, we'll need to render many messages. For example, consider the sequence of events:

  • Monday, 8:00am - The user, Alice, starts writing a message.
  • Monday, 8:10am - Alice requests a preview. The "Composer" sends a copy of the message to the "Manager".
  • Monday, 8:11am - The "Renderer" asks the "Manager" if there are any new messages to render. The "Manager" returns Alice's message
  • Monday, 8:14am - The "Renderer" completes rendering. It sends a copy of the screenshot to the "Manager".
  • Monday, 8:15am - The "Composer" asks the "Manager" if the screenshots are available yet. The "Manager" responds with the details.
  • Monday, 8:15am - Alice sees the screenshot and dislikes it. She makes starts making some changes.
  • Monday, 8:20am - Alice requests a preview. The "Composer" sends a copy of the revised message to the "Manager".
  • Monday, 8:21am - The "Renderer" asks the "Manager" if there are any new messages to render. The "Manager" returns Alice's new message
  • (The process repeats.)

During its lifetime, the renderer may run continuously for several months, and it may handle dozens/hundreds/thousands of different messages (eg different drafts of the same newsletter; or entirely separate newsletters). Whenever a user submits a new message (eg ~8:10am or ~8:20am), the renderer needs to find out about it (~8:11am or ~8:21am) and start rendering it.

There are a few different ways to arrange this. Polling is one technique. It has some disadvantages (eg there's 1 minute delay between the submission at 8:10am and the start at 8:11am), but it also has some advantages (simple, widely used, compatible with RESTful architecture).

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 14, 2015, 07:41:29 pm
Got it. Thank you so much for the great explanation. :) I'll try implementing all that in the coming few days.
Loading the email from a remote file is done.
However, phantomjs is posing some problems. But it shouldn't be a really big issue. I'll get around it in a day or two hopefully.
I haven't yet started working on extending the code to another email client. How should I go about it? One after the other or parallely (if that's possible)?

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Email Preview Cluster
June 15, 2015, 09:55:01 am
Quote from: utkarshsharma on June 14, 2015, 07:41:29 pm
I haven't yet started working on extending the code to another email client. How should I go about it? One after the other or parallely (if that's possible)?

For now, let's treat it as part of the htmlEmail.json document. For example, the JSON document might say:

Code: [Select]
{
        "subject": "Renderer Testing",
        "body_html": "<h1>This</h2> <p><b>message</b> <i>is</i> a <u> test message</u>.",
        "body_text": "This message is a text message",
        "render_with": "gmail"
}

The webmail renderer would inspect the "render_with" property and kick off the appropriate logic. The end-user (or the Composition UI) will make the judgment about which clients they want to render with, and the Manager will pass that along.

Re: parallel execution... Should the webmail-renderer support concurrent jobs within one instance of "node main.js"? It's not a hard requirement. (Even if main.js were strictly single-threaded/single-job, one could scale out by launching multiple copies of "node main.js".) But supporting multiple jobs within one instance of "node main.js" would improve efficiency in high-demand scenarios. Recommendation: Take whichever route feels easier.

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 17, 2015, 11:10:41 pm
Yahoo is working as well! (single-threaded)
Now polling and PhantomJS remain  ;D

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 21, 2015, 04:11:35 am
PhantomJS works for Gmail. But, with Yahoo, it's being very unpredictable. It logs into the Yahoo Mail account in some test runs and doesn't in others. And when it does, not all the elements (including the search bar, which is vital to our purpose) get loaded. I find Firefox and selenium much more reliable. Earlier, even I was excited about using PhantomJS, but now Selenium with Firefox looks like the better option to me. Is there a particular reason we want to use PhantomJS?

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Email Preview Cluster
June 22, 2015, 03:57:34 pm
It's great that Yahoo/Selenium and Gmail/Phantom is working. Could you 'git push' (and generally do so more regularly)?

Quote from: utkarshsharma on June 21, 2015, 04:11:35 am
Is there a particular reason we want to use PhantomJS?

There are two reasons I've pushed for Phantom.

The first reason is "npm" and simple installation. If you put PhantomJS in "package.json", then you can download everything in one command ("npm install") which works on basically any desktop or server. I don't know a comparatively simple/effective way to download and configure Selenium+Firefox. (Simpler installation means simpler documentation / less support / more successful installs.)

The second reason is based on some experience using similar tools in Civi's testing infrastructure. (That's a slightly different problem space; easier in that we control the entire webapp, but harder in that we have many more scripts/scenarios to test.) Anyway:

  • For Javascript unit-testing, we use Node+Jasmine+Karma+PhantomJS. This is a newer/smaller suite, but so far it's performed reliably. (It starts consistently; given the same inputs, it always produces the same outputs.)
  • For end-to-end/click-through testing, we use PHPUnit+Selenium+Firefox, and it's been unstable for a long time (despite several projects to try to workaround). If you leave selenium-server.jar running continuously, it breaks down every 1-4 weeks. ("Breaks down" => the daemon is running and answering requests but mostly returns errors.) If you stop/restart periodically, selenium-server.jar often hangs during the restart. (Aside: Found a possible explanation last week -- https://code.google.com/p/selenium/issues/detail?id=8237#makechanges ).

So... I'm partial to Phantom over Selenium, and it's really unfortunate that Phantom doesn't run consistently on the Yahoo Mail. But we don't want it to become a big drag on the project. Let's get a couple eyes on the Yahoo Mail script (just in case). If that doesn't turn up anything, then we could do one of:

  • Try the Yahoo Mail script using Selenium+Chrome (aka "*googlechrome"). This puts it about halfway between the Selenium+Firefox and Phantom configurations -- and may help identify/narrow the problem. (eg If the inconsistency involves a Webkit-vs-Gecko issue, then we'd expect PhantomJS and Chrometo fail the same way.)
  • Flag the Yahoo Mail script as experimental. (The main goal here was to ensure that the app has enough abstraction to support multiple webmail systems, and that goal is met even if the Yahoo support is unstable.)
  • Just accept that the installation/administration requires Selenium and Firefox for now.

utkarshsharma

  • I’m new here
  • *
  • Posts: 22
  • Karma: 0
  • CiviCRM version: 4.5.8
  • CMS version: Drupal 7
  • MySQL version: 5.5.41
  • PHP version: 5.5.9
Re: Email Preview Cluster
June 22, 2015, 07:40:58 pm
Polling is done. But PhantomJS is not being used in the code.
Changes pushed to git. (Will try to do so more often.)
I put a flag called "newTask" inside the htmlEmail json element for the renderer to identify if there is indeed a task for it that needs to be completed. The renderer script will only run if that flag is found to be 1.
This might not be the way we're going to do it in the final project. I have just put the flag there temporarily.

I'll work more on PhantomJS and try to make it work with Yahoo as well, or we'll go forward with what all you've suggested.

Pages: 1 [2] 3
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • Google Summer of Code »
  • Email Preview Cluster

This forum was archived on 2017-11-26.