Trying to Automate Emails

I’m having a challenge setting up for sending emails via mail merge. The actual sending works, but I’m trying to setup for various types of emails.

I have a form GenerateEmails based on the EmailTypes table:
EmailTypesKey (text) : GENERIC, BOARD or LEADERS
EmailType (text) : Generic Email, Board Reports or Study Group Leaders
Seq (integer) : to select the records in the desired order
DefaultSubject (text)
DefaultBody (memo)

I’ve added fields to the GenerateEmails General page, which are not coming from the table, in the hopes of using them like screen fields in reports or processes.

I’ve added a page called Members which shows the SelectedMembers table records via a DataView. When any of these members are clicked, it “flips” the IsSelected value for that member in the SelectedMembers table. The intent is to collect all the members with IsSelected=true and create a string of email addresses. This part is working fine. What I want to do is populate that list into the To textbox on the General page. This part is not working. I can’t figure out how to populate a textbox via its fieldID. There is no entry in the Field property, because I’m not storing these values, just using them to send the emails.

It seems to me I either need to figure out how to populate that text box with the value I want, or perhaps switch to a process instead, which does allow screen fields.

If I switch to a process, then of course I can’t have a second page showing Members. I would have to open a new form to select members from a DataView, then click a button to return to the process. I can do this with a form using previousAction. I don’t know if that works to return me to a process.

So, Can I return to the process that was active before I opened a form? This is working fine from Form → Form → Back to Form. Just don’t know if it works to return to a process.

I need advice on how to accomplish this requirement in Five.

Which is better, using a form or a process to start with?

If either is equivalent, a form is somewhat easier, but must figure out how to populate an unbound textbox, then use its value when actually sending the email.

The intent of all this is to create an email containing default subject and text (stored in the table), display those in the form, be able to add or change the text of the To, Subject or Body textbox, then send the email.

I don’t really want to save any changes such as To, Subject or Body text, so it doesn’t make sense to add those to the table, because once changing them, I’d have to clear those fields and save the record.

I hope I’ve described the issue properly, and that you can tell me how to accomplish this in Five. Thanks…

Hi Ron,

In your solution, my understanding is that you want the email string to be populated in a textbox so it can be reviewed or modified before the email is sent.

You can still achieve this using a form with a Data View page. I would suggest the following approach:

  1. Make sure your General form has the field ‘Page Navigation’ set to ‘Top’ (not ‘Continuous’).

  2. Save the email string into a Five variable, and ensure this variable is available on the Data View page.

  3. On the General page record, add a function (for example, GetEmailOnSelecting) and attach it to the On Selecting event. This event will be triggered every time you navigate to the General tab.
    3.1. The function will populate the textbox with the email string.

If you want to allow changes to the email string, I recommend the following enhancement:

  • Add a new button to the General page, for example, Refresh Email List. This button should only be displayed when the textbox is empty.

    • The reason for this is that when you click the Edit button, any values populated by the GetEmailOnSelecting function are cleared, since the form is now in edit mode and the field is being manipulated manually.
  • Attach the same GetEmailOnSelecting function to the On Click event of this new button.

With this setup:

  • When you navigate to the General tab, the textbox is automatically populated.

  • If you click Edit and start modifying the field, the textbox will be cleared.

  • The Refresh Email List button then becomes visible, allowing you to repopulate the textbox with the original email string stored in the Five variable—this time in edit mode.

This creates a clean and flexible workflow, giving you the choice to either edit the email list or reuse the generated one.

I’ve also put together a quick sample app that demonstrates a similar UI behaviour (although it doesn’t generate an actual email). In the tab list, clicking a button generates an email and stores it in a Five variable. When you switch to the General tab, this email appears in the Email field. Once you edit the form, a new button appears to regenerate the email content. Clicking Send Email then displays the contents of the Email field, which could be passed to a server function to send the email.

I hope this helps.

If you prefer a different approach, you can use a dummy table to store the list of email strings. The email content can be generated in the Data View and saved to this dummy email table. By opening the corresponding form, you can then review and modify the email field before executing the mail merge.

This approach is more straightforward, though it requires the use of separate menus.

Regards,
Elton S

FilterCustomer-Trying to Automate Emails_Forum_610.fdf (3.4 MB)

Thanks so much for the example Elton!

Here is the code, which I basically copied from your project with a few changes.

function UpdateEmailTo(five, context, result) {

    const emailTo = five.getVariable('EmailToMembers');
    if (!emailTo) {
        return five.success(result);
    }
    five.log(`UpdateEmailTo: emailTo=${emailTo}`);
    const field = five.sender();
    const dataManager = field.dataManager;
    dataManager.setValueByName('SendTo', emailTo);
    dataManager.setModifiedField(field.formField.key());
    field.refresh();

    five.clearVariable('EmailToMembers');
    
    return five.success(result);
}

This seems to work, sort of. If I have my form open, but not in edit mode, then I click over to the Members page, then click back to the general page, any members who are selected in the dataview will cause their emails to appear in the SendTo field. So far so good.

However, if I then click on the field to go to edit mode (or click the pencil icon), the new text disappears from the form field. If I was already in edit mode, this doesn’t happen, but I also notice there is no save checkmark at the top, there is only trashcan and X. If I instead type something in that field, there is trashcan, X and Save.

I notice on your application, it acts pretty much the same. So your code seems to be working on the form field, not the associated table field. but the moment you go into edit mode, the new email list disappears, and is replaced with what was saved in that field in the table.

So it seems this will only work properly if I was already in edit mode, right? Even then, the save button doesn’t always remain at the top. So this almost works.

I only added the SendTo field into the table because I couldn’t get anything to work if I have the form field bound to the table field. I didn’t even want the table to have the To, Cc, Bcc, Subject and Body fields. I only added them in there because I couldn’t figure out how to update form fields with no associated data field.

UPDATE: Of course I was doing it wrong, and now I just tried it by removing the table field name from the field in design mode, and it still works (using your technique). This is huge! What I really wanted was like a process with screen fields. Unfortunately I can’t have pages on a process. If I remove all table field names from my form fields, I think I can get this to work. There are table fields for DefaultSubject and DefaultBody, which are hidden on this “processing” form. They would be edited on the “setup” form for these emails. Somewhere on the form open event I would copy the values from the hidden default fields into the unbound processing fields, where I can then edit them and click an action button to actually create the email.

I don’t know why the save button disappears, but I don’t really want to save these records, just use them to send emails.

I will continue to work this form and see if I can get it to work. Don’t know yet if when I click the button to create emails and in the function code that runs I refer to five.field.whatever, whether that will refer to the screen field or not.

Do you have any input on that?
IMPORTANT: If I’m using an unbound field (not related to a table field), what is the limit of characters I can put in there? there is no field length like on table fields. If I give it a display type of _Text, what is the size limit? How about with _Memo?

Thanks!!!

Hi Ron,

Just to make sure we’re on the same page:

In my sample app, when you click the Edit button (or click into the Email field), the email content disappears. This happens because values are being added behind the scenes. When this occurs, a new button called “REFRESH EMAIL LIST” appears. Clicking this button restores the data to the field, allowing you to edit it without losing any content, and having the Save button.

Because of this flow, there’s no need for a Save button like the one in my example. Instead, you can include a “SEND EMAIL” button in the form, which triggers a callback function to send the email based on the list of email addresses. In my scenario, I only used a showMessage(), so you can see that all values from the email field are correctly retrieved.

In the application I sent you, please use only the Customer menu, specifically the List tab.

If you prefer to use a Save button to store the data, the approach would need to be different.

Additionally, in your function, you are cleaning the value five.clearVariable(‘EmailToMembers’);
I suggest you only clear this variable when you send the email, because you need to trigger the same function when clicking on the button “REFRESH EMAIL LIST”, like in my example, so the value is still there to be reused/sent back into the Email field.

Please let me know if I misunderstood your comment.
———————————————————————————-

Regarding the display type, you can create a new display type based on a ‘Memo’, and give a minimum and maximum number of lines, then add this display type to your form field. The image below shows one example of it.

Regards
Elton Santos

Thanks for reply.

I mainly wanted to know how many characters would the field hold if it was _Text, and also if it was _Memo.

Not sure what I gain by creating the new display type. what do min and max lines do?

Also, To field is _Text. If there are several email addresses, they don’t fit visually in the form field. is there a way to make this scrollable?

Also, the logic is working, and the default subject and body are appearing on the form fields. they are not bound to the table, but when I edit them, the checkmark save button appears. I believe if I have an action button, that replaces the checkmark, right? This form is designed to not be saved.

Thanks for your idea about the Memo display type. that worked like a charm.

thanks…

Next step:

I want to automate generating the reportResult objects. Given that my SelectedReports table will have a list of all reports with UserKey, ReportKey, ReportTitle and IsSelected, I am thinking about a server function that will return either an array or dictionary of reportResult objects. Then I will use this to generate the email(s).

ChatGPT thinks the reportResult object is too complex to return in a dictionary or json object because it contains methods and/or properties in addition to the report PDF. Please advise if this is true. I was picturing looping through the returned object, and for each one, generate the email to the appropriate people on the client side. Here is some code you gave me that works for a single report:

function EmailSelectedReports(five, context, result)  {

    const _five = five;
    // const sendTo = five.field.EmailReportsToKey;
    five.log('EmailSelectedReports');
    // five.log(`EmailSelectedReports: sendToType = "${five.field.EmailReportsToKey}"`);
    
    // const exportResult = ExportReports(five, sendTo);
    // five.showMessage(JSON.stringify(exportResult));
    
    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Execute the report action
    ////////////////////////////////////////////////////////////////////////////////////////////////
    /*
    const reportResult = five.executeAction('Roster', {UserKey: five.variable.UserKey});
    if (reportResult.isOk() === false)   {
        return five.createError(reportResult);
    }
    */
    ////////////////////////////////////////////////////////////////////////////////////////////////
    // The reportResult contains a parameter called report, which is the report result in the format
    // of a pdf (encoded as data url application/pdf mimetype)
    ////////////////////////////////////////////////////////////////////////////////////////////////
    /*
    const mailMergeContext = {SMTPToEmail: five.field.EmailAddress, SMTPToName: "Staff", SMTPAttachments: [reportResult.report]};
    const mailResult = five.executeAction('ReportEmail', mailMergeContext);
    if (mailResult.isOk() === false) {
        return five.createError(mailResult);
    }
    */
    return five.success('Report has been sent');
}

Ignore the comments, as this function will work when uncommented for a single report. The question is if I use a server function to return a json object for all the reports selected, will the value of each reportResult be guaranteed to be correct as it is if I call it for one item, as in the code above?

Also, I’m not sure what ExportReports is in the above code. is it a server function or built-in five functionality?

Actually, the above code seems to be a server function, because in my process, which was running properly for a single report, it is called from the DoRun event, right?

What I’d like to end up with is a single server function to create all the reportResult objects and return them. is this doable?

Thanks…

Hi Ron,

Could you please open a new question so we can keep the topics separate? Also, please let me know if my previous response resolved the original question.

Regards,
Elton S

Thanks for your detailed response Elton. Once I removed the binding on the field, everything works. Your code made it possible to load the unbound SendTo field on the form with the proper emails. I do not need to figure out a way to re-scan or refresh the email list anymore. every time I move off the General tab and move back again, the event causes the SendTo field to be refreshed. Next step: instead of simply replacing the field contents I will selectively refresh from the SelectedMembers table. This will enable a desired feature of allowing the user to also type in email addresses, then not lose them if the user then selects more members on the Members page.

Thanks So Much!