emailing list of contacts not changing the firstname in list
I have done a script to send an email to all valid contacts to update the prices. It all works fine except that I have an issue
in that the contact first name is only picking up the name of the record that I am on when I fire the script from and applying that name to all the emails html body letter
instead of changing it to each users name - FirstName ?
any suggestion?
Here is full script
"-----------------------------------------------------------------------------------";
"This code selects contacts where a Yes/No field (Send Email) is set to yes and GDPR = 1 (Opted In)";
"Then it loops through the records sending an email and re-setting the 'Send Email' flag to no";
"-----------------------------------------------------------------------------------";
for recipient in select Customers where 'GDPR Status' = 1 and 'Send Email' do
let thisBody := first((select SystemFile).Letter2);
let myEmail := userEmail();
let xFirst := FirstName;
let myAtt := first(files(record(SystemFile,1)));
thisBody := replace(thisBody, "{FirstName}", xFirst);
sendEmail({
from: myEmail,
to: recipient.Email,
subject: "Cusromer Price List Update",
text: "New updated price lits for your files",
html: thisBody,
attachments: myAtt
});
recipient.('Send Email' := 0)
end
20 replies
-
ignore the text type in subject line !
-
Change to:
let xFirst := recipient.FirstName
....
Steven
-
Styeven
I can't believe I missed that!
Sometimes you can't see the wodd for the trees!
Thank you for the casting the fresh pair of eyes over the script.
One day and I do mean one day I will manage to help you in return !!!
kind regards
Mel
-
Steven
I want to limit the above script to a batch of 75 records at a time
what's the best approach to achive this?
I've tried couple of things like example further below but whilst the script is accepted it ignores it at run time.
I'm guessing the condition of select, where and do it literally working through all files
let myC := 1
then adding
for recipient in select Customers where 'GDPR Status' = 1 and 'Send Email' and myC <75 do
the adding further down
let myC := myC +1 etc
-
Off the cuff....
Try this: ('Emailsend' is an extra yes/no field if you haven't got one in your table Customers)
let sendmails := select Customers where 'GDPR Status' = 1 and 'Send Email' and Emailsend = false;
let myCount := if cnt(sendmails) > 75 then 75 else cnt(sendmails);
for i in range (0,myCount) do
let thisBody := first((select SystemFile).Letter2);
let myEmail := userEmail();
let xFirst := item(sendmails,i).FirstName;
let myAtt := first(files(record(SystemFile,1)));
thisBody := replace(thisBody, "{FirstName}", xFirst);
item(sendmails,i).Emailsend := true;
sendEmail({
from: myEmail,
to: recipient.Email,
subject: "Cusromer Price List Update",
text: "New updated price lits for your files",
html: thisBody,
attachments: myAtt
});
recipient.('Send Email' := 0)
endIt might need some tweaking, let me know if it works....
let xFirst := record(Customers,item(sendmails,i)).FirstName; (if the above doesn't work change this)
record(Customers,item(sendmails,i)).Emailsend := true; (if the above doesn't work change this)Steven
-
Hi Steven
Thank you - I haven't tried the other options at the botton co I can't get past an error
let sendmails := select Customers where 'GDPR Status' = 1 and 'Send Email' and Emailsend = false;
let myCount := if cnt(sendmails) > 75 then 75 else cnt(sendmails);
for i in range (0, myCount) dothis line in bold is giving me a field not fount error (col 26)
seems to think that myCount is a field and not a variable as defined in line 2
My 'Send Email' Field is a yes/no flag to add extra control over the gdpr status (so if both are true send the email out) then set send email to false
So is your extra Emailsend (yes/no) field needed ?
cheers Mel
-
Try:
let myCount := if cnt(sendmails) > 75 then 75 else cnt(sendmails) end; <--you need an end to close the if statement.
-
Thanks Fred, didn't see that.
-
Fred/Steven
This is really getting there !
There is just a small issue in that it was now giving me an error in as shown the bold lines below as they are no longer recognised
ie was previous refering to by following line (recipient variable)
for recipient in select Customers where 'GDPR Status' = 1 and 'Send Email' do
ah - I though maybe then I need to replace recipient for sendmails?
tried this all it works BUT if grabs every email due to go and sneds it to every one - so say there is a batch of 6 emails - it sends 6 emails with each name added to the send to address box
so technically 36 emails were send out and each contact got 6 emails all saying the same with all contacts visable in the sent to box
so clearly that is not right - although I am not sure how to correct this ? Somehow i still need to define recipient and not have the loop?
it send this 6 times to each group!
let sendmails := (select Customers where 'GDPR Status' = 1 and 'Send Email' and EmailSend = true);
let myCount := if cnt(sendmails) > 75 then 75 else cnt(sendmails) end;
for i in range(0, myCount) do
let thisBody := first((select SystemFile).FollowUpLetter);
let myEmail := userEmail();
let xFirst := item(sendmails, i).FirstName;
let myAtt := first(files(record(SystemFile,1)));
thisBody := replace(thisBody, "{FirstName}", xFirst);
item(sendmails, i).(EmailSend := true);
sendEmail({
from: myEmail,
to: recipient.Email,
subject: "Thank you for past purchases from 118Printgroup, but did you know we print much more?",
text: "from 118 Printgroup",
html: thisBody,
attachments: myAtt
});
recipient.('Send Email' := 0)
end -
Hi Mel -
1) what happened to the recipient variable? if you changed it to sendemails then you need to replace all instances of recipient.
2) in the "to" section, I think you might need to so something like you for xFirst.
-
Fred
I used stevens last example. He removed the recipient from the definition and left it in further down - so i did the same.
I've stripped the code back to remove the attachments etc that I know works (I'll add code back later) just to show show where I am (i've changed the recipients variable to myPost (just for abit of clarity).
let myPost := (select Customers where 'GDPR Status' = 1 and EmailSend = true); This line works (if there are 6 value in the list it selects all 6)
let myCount := if cnt(myPost) > 3 then 3 else cnt(myPost) end; (this definately selects only 3 emails to send out)
for i in range(0, myCount) do
let myEmail := userEmail();
let xFirst := item(myPost, i).FirstName;
item(myPost, i).(EmailSend := false);
sendEmail({
all this section works - so no issue here
});
myPost.(EmailSend := 0)
endbut what actually happens is that 3 emails are sent but all 6 vaild emails are attached to each of the 3 emails
so in this case each email copy to 6 users - giving 18 emails gone out
I'm confused now !!!!
-
if i move this line from the middle and put it at the end
item(myPost, i).(EmailSend := false)
then the script correctly detects 3 email to go out and sets the correct qty of the EmailSend flag back to false instead of all 6 in the list.
but the actual email going out then does not work at all :-(
-
So in essence !!
The counter is picking up the first email then adding all the valid emails into that first email then moving onto counter 2 and doing the the same
I'm struggling to see how I can break down the select query line so that it only get one email at at time. Obviously without the counter lines added - The script ran fine.
Albiet - I would have to manually run down the table view, setting 'EmailSend' to true for the amount I want to go out in a batch.
But given that I have over 600k customer records and to then manually set 75 at a time would be quite an undertaking!
-
Hi Mel
You don't need to add any counter lines. Take your select statement and then scope this to the first 75 lines
let a:= select Customers where 'GDPR Status' = 1 and 'Send Email';
for recipient in slice(a, 0, 75) do
The rest of your initial script can stay the same, especially as 'Send Email' is set to 0 as this runs, so next time the script will run using the next 75 customers.
Regards John
-
Hi John
YAY !! - That works !!!
For testing - I changed the 75 to a batch of 3. Fired it off twice - It did exactly what you said it would and effectively walks down the list.
That's great because across all my customers list. I can set a sensible batch per day and simply fire the button off when I'm ready.
Alsi I can now set the table view to sort descending on sendemail and i wil always know where i am.
Once the list is walked through I can do a table update with a contant value to reset sendmail.
Thanks for this :-)
What does slice do?
Fred/Steven
I would still like to get my head around the counter/select though please to see if a solution is still possible this way.
I need to understand how the counter was trying to count but then including all the email in the sedning then mnovining onto count 2 then doing the same.
I really appreciate the time and support you guys give me! - THANKYOU!
Kind regards
Mel
-
That's great Mel
slice gives you a subset of an array
slice(array, start, end)
Arrays start counting from 0 ( so 0 is the first element of the array) and the start is inclusive but I think end is exclusive (so 75 still gives you 75 elements even though it started at 0)
Regards John
-
ah John
Got it - slice is a method used with strings to return all characters after a start position or between 2 points
that's a new one learned !!
-
In essence, you get an array with all the Id's of the table when you use a select statement e.g. [1,5,100,155,255,688,697,789,790,791,792]
So we have now an array of 11 values. Suppose you wanted to send 12 email at a time.
with the slice function we divide the found Id in slices of 12. cnt(array) tells there is only 11 so the counter should be 11 and not 12:
myCount := if cnt(array)>12 then 12 else cnt(array) end
now sending emails to the array list (with the function item() selecting the Id's of the array:)
The first item of an array has position 0 (zero) and the last position has variable: myCount - 1 or like John use it : slice(myCount,0,11) With slice, he shortens the array to 12.
now we say: for i in range(0,myCount-1) do is telling to select the first Id untill the last Id (contained in i) which is in the list of the array , send an email with i.Emailadres
If you put this code in a button, the more you pusch the button, the less records would be selected in your select-statement if you have a field like 'EmailSend' if the email was already send.
Hope this explains the code a little more.
Steven
-
My guess, since I don't have a db to try this one. Is that in the counter situation, you are not telling the for statement to use a specific email address. I think I asked earlier about the to section of the email. It basically said:
to: recipient.Email
I think you have to do something like:
item(myPost, i).Email;
Once you switched to a range you have lost all connection to any records. That is why John's method is better. Your last connection to your records is in your myPost variable. So you need to do what you did for FirstName, you have to pull the record Id from your MyPost and then get the email address of that record.
Which I think your reporting say that this is exactly what it is doing. You said it found 6 records. Then it sent out 3 email to all 6 records. So your data set has 6 email addresses that Ninox adds to the to line and sends it out 3 times cause you limited the range from 0 - 3
John's method keeps the reference to the record so you can use your basic code cause Ninox is only working on one record at a time.
Hope this helps.
-
John/Fred/Steven
Thank you for various explanations. That really helps !
As stated before, I'm not a coder in any way but see it as a task to do in order to drive my business. That said I have progressed quite some way.
This issue for me (and I guess many others!) is that I don't know - what I don't know!.
Hope that makes sense so when faced with some problems. I can full state it in English how to work through the problem, but transfering that into code/script can be problematical when a) You have no model to base it on. B) You don't have the knowledge of all the scripts etc.
As with most things it relys on experience gained with Practise, Understanding and Feedback.
You guys help make that process easier ! - Thank you as ever :-)
P.s Although I know I have the solution now. I'm going to carry on see if I can get the script working fully using the counter method.
Content aside
- 3 yrs agoLast active
- 20Replies
- 895Views