How do I Show a SPList item Name in an Email sent by a timerJob? - email

I need to send an Email with a list items name of the rows my caml query picks out. I have this code:
SPQuery filter = new SPQuery();
filter.Query = string.Format("<Where><Leq><FieldRef Name=\"Revisionsdatum\" /><Value Type=\"DateTime\">{0}</Value></Leq></Where>", DateTime.Today.AddDays(14).ToString("yyyy-MM-ddThh:mm:ssZ"));
SPListItemCollection items = yourList.GetItems(filter);
foreach (var i in items)
{
string from = string.Empty;
string smtpAddress = string.Empty;
string to = "Someone#someCompany.com";
string subject = "Dudate is coming";
string body = "<h1>Hello!</h1><p>In to weeks an importent dudates comes({0}) with the name {2}.";//Here I would like to ad the dudate and the ListItems Name but how?
// get a reference to the current site collection's content database
SPWebApplication webApplication = this.Parent as SPWebApplication;
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
// get a reference to the "Tasks" list in the RootWeb of the first site collection in the content database
SPWeb rootWeb = contentDb.Sites[0].RootWeb;
SPList listjob = rootWeb.Lists.TryGetList("Tasks");
// Get sender address from web application settings
from = rootWeb.Site.WebApplication.OutboundMailSenderAddress;
// Get SMTP address from web application settings
smtpAddress = rootWeb.Site.WebApplication.OutboundMailServiceInstance.Server.Address;
// Send an email if the news is approved
bool emailSent = SendMail(smtpAddress, subject, body, true, from, to, null, null);
}
I would bee greatfull for your answer!

You can get it as follows:
foreach (SPListItem item in items) \\ items is your SPListItemCollection
{
var fieldValue = item["Field Name"].ToString();
}

To convert DateTime object to CAML query use SPUtility.CreateISO8601DateTimeFromSystemDateTime() method.
Fields you need are referenced by i["Title"] and i["DueDate"].
Use StringBuilder object in foreach loop to construct the body of your mail and send the email after the loop. Your code will send one mail for each task.

Related

MailKit HtmlBody Always Null

I"m trying to get the html from an email retrieved in Gmail. No issues getting the emails however when I attempt to get the HtmlBody it is always null. HTML is present according to the bodyparts.
using (var imap = new ImapClient())
{
imap.Connect("imap.gmail.com", 993);
imap.Authenticate(Login, PW);
var inbox = imap.Inbox;
inbox.Open(FolderAccess.ReadWrite);
string body = "";
if (html)
{
body = inbox.GetMessage(messageID).HtmlBody;
} else
{
body = inbox.GetMessage(messageID).TextBody;
}
imap.Disconnect(true);
return body;
}
I can see from the bodyparts that html is present and if I use this linq I'm able to get the encoded html.
var msg = inbox.GetMessage(messageID).BodyParts.OfType<MimePart>().First(x => x.ContentType.MimeType == "text/html");
Using this I can see there is a Text property but I'm not able to retrieve it. Can anyone assist in getting the unmodified html from Mailkit?
If you change your LINQ statement to:
var msg = inbox.GetMessage(messageID).BodyParts.OfType<TextPart>().First(x => x.ContentType.MimeType == "text/html");
... you'll be able to access the .Text property.
The other option is to cast the msg variable to a TextPart.
The reason you can't access the .Text property in your current code is that this property only exists on the TextPart subclass of MimePart (which is more abstract).

Google Apps Script_populate multiple templates depending on google form data and then email pdf copies

Help greatly needed.
Using Google Form to gather data, in order to populate one of 2 Google doc templates, dependent on whether option 1 or 2 is chosen in the Google form. Populated template to be saved in "final" folder as a PDF, and then emailed to the email address submitted in the Google form.
Currently, I'm able to generate the correct PDF files in the correct folder and send the email to the correct address, but there is no attachment and just the words [Object object].
Before I included the if/else function, I was able to correctly send the email with attachment, which means that I've caused a problem with the if/else and naming of the generated pdfs. I just can't figure it out.
function autoFillGoogleDocFromForm(e) {
//form values
var timestamp = e.values[0];
var firstName = e.values[1];
var lastName = e.values[2];
var email = e.values[3];
var multiplechoice = e.values[4];
if (multiplechoice == "Template 1") {
//This section will complete template 1
var file = DriveApp.getFileById("Template 1 ID");
//Create copy of Template 1
var folder = DriveApp.getFolderById("Templates folder ID")
var copy = file.makeCopy(lastName + ',' + firstName, folder);
//Open copy of Template 1 and replace key fields per form data
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
body.replaceText('{{First Name}}', firstName);
body.replaceText('{{Last Name}}', lastName);
doc.saveAndClose();
Utilities.sleep(1500);
} else {
//This section will complete Template 2 by default
var file = DriveApp.getFileById("Template 2 ID");
//Create copy of Template 2
var folder = DriveApp.getFolderById("Templates folder ID")
var copy = file.makeCopy(lastName + ',' + firstName, folder);
//Open copy of Template 2 and replace key fields per form data
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
body.replaceText('{{First Name}}', firstName);
body.replaceText('{{Last Name}}', lastName);
doc.saveAndClose();
Utilities.sleep(1500);
}
//create pdf copy of completed template either 1 or 2 depending on IF
var pdffolder = DriveApp.getFolderById("Templates folder ID");
var pdfFILE = DriveApp.getFileById(copy.getId()).getAs('application/pdf');
pdfFILE.setName(copy.getName() + ".pdf");
var theFolder = pdffolder;
var theFile = DriveApp.createFile(pdfFILE);
theFolder.addFile(theFile);
Utilities.sleep(1500);
var subject = "File attached";
var attach = theFile;
var pdfattach = attach.getAs(MimeType.PDF);
MailApp.sendEmail(email, subject, {attachments: [pdfattach]});
}
There are two signatures of MailApp that support attachments:
sendEmail(message)
and
sendEmail(recipient, subject, body, options)
There isn't a sendEmail(recipient, subject, options) method signature.
Include a body argument:
MailApp.sendEmail(email, subject, "☢☣☢",{attachments: [pdfattach]});

E-mail notification based on cell value. Unable to apply script function for all rows

I am using Google sheets and the Google script editor to create a script to automatically send myself an e-mail every time a product quantity goes below the minimum inventory level. Since I have multiple products with different minimum inventory levels I expect to get a series of e-mails, one for each row.
I use one sheet for the actual Inventory data and another sheet that contains information for the script to refer to, such as my email and what message to include in the e-mail.
I succeeded having an e-mail sent collecting data from the first row of the Inventory sheet but I am not being able to apply that for all the following rows.
I tried changing the .getRange("F2") to .getRange("F2:F"), then whenever one of the products goes under the minimum inventory level I get one single e-mail containing the information about all products, regardless of whether their quantity is under the minimum level or not.
The ideal solution would be ONE single e-mail containing all the information about all products that are under the minimum quantity .
Here is a link to my spreadsheet: https://docs.google.com/spreadsheets/d/1ZHmBvi8ZeaDRYq6Qigaw08NUiOwZumPrLnvnka_mgmA/edit?usp=sharing
Current script:
function CheckInventory() {
// Fetch inventory quantity
var InventoryRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inventory").getRange("F2");
var Inventory = InventoryRange.getValue();
// Fetch minimum quantity
var MinimumQuantityRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inventory").getRange("D2");
var MinimumQuantity = MinimumQuantityRange.getValue();
// Check Inventory
if (Inventory < MinimumQuantity){
// Fetch email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Notification Rules").getRange("E2");
var emailAddress = emailRange.getValues();
// Fetch email message details.
var detailsRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Notification Rules").getRange("G2");
var details = detailsRange.getValues();
var subjectdetailsRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Notification Rules").getRange("H2");
var subjectdetails = subjectdetailsRange.getValues();
// Send Alert Email.
var message = details;
var subject = subjectdetails;
MailApp.sendEmail(emailAddress, subject, message);
}
}
Update:
As you said in a comment, you want the email to be sent when you edit an inventory cell, and only if this edited inventory quantity is below the corresponding minimum. So here I update my answer accordingly.
First, I guess you have done this already, but because the function uses sendEmail, you will have to grant authorization for it to work. I created a trigger for that. Run this once:
function createEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger("CheckInventory")
.forSpreadsheet(ss)
.onEdit()
.create();
}
Then, this is the function that will run every time the spreadsheet is edited. To avoid the email to be sent every time the file is edited, we need a condition that checks whether the edited cell is an inventory and that this inventory is below the minimum:
function CheckInventory(e) {
var ss = e.source;
var inventorySheet = ss.getSheetByName("Inventory");
var rowIndex = e.range.getRow();
var columnIndex = e.range.getColumn();
var numCols = 6;
var row = inventorySheet.getRange(rowIndex, 1, 1, numCols).getValues()[0];
var editedInventory = row[5];
var editedMinimum = row[3];
var sheetName = ss.getActiveSheet().getName();
// Checking that: (1) edited cell is an inventory quantity, and (2) Inventory is below minimum
if(editedInventory <= editedMinimum && sheetName == "Inventory" && columnIndex == 6 && rowIndex > 1) {
var inventoryValues = inventorySheet.getDataRange().getValues();
var emailBody = "";
for(var i = 1; i < inventoryValues.length; i++) {
var inventory = inventoryValues[i][5];
var minimum = inventoryValues[i][3];
if(inventory <= minimum) {
var productName = inventoryValues[i][0] + " " + inventoryValues[i][1];
var productUnits = minimum + " " + inventoryValues[i][4];
var messagePart1 = "Inventory for " + productName + " has gone under " + productUnits + ". ";
var messagePart2 = "Organise purchase order. Inventory as of today is: " + inventory + " " + inventoryValues[i][4];
var message = messagePart1.concat(messagePart2);
var newItem = "<p>".concat(message, "</p>");
emailBody += newItem;
}
}
var emailSubject = "Low inventory alert";
var emailAddress = "your-email#your-domain.com";
// Send Alert Email
if(emailBody != "") {
MailApp.sendEmail({
to: emailAddress,
subject: emailSubject,
htmlBody: emailBody
});
}
}
}
As I said in a comment, if you just want to send an email, it doesn't make sense to have many email subjects, so I hardcoded the subject.
Regarding the emails, I assumed you just want an email address to receive the email, so I hardcoded it too. If you want all the different email addresses found in Notifications tab to receive emails regarding all products, a small fix would be needed to this code. Tell me if that's needed for you.
Also, I didn't use your notifications tab at all, I created the message directly using the script. I'm not sure it is that useful to have the sheet "Notification Rules". Much of its info is the same as the one in inventory, and the rest of data (email address, basically) could be easily included there. But whatever suits you.
I hope this is of any help.

Send Email fields not rendering in Sitecore Web Forms For Marketers

I have an issue with the WFFM Send Email Message save action (Sitecore 6.5.0). I'm trying to send an email that includes the form placeholders from the "Insert Field" dropdown in the Send Email editor. Sometimes the fields will render correctly, but most times the email will include the placeholder text instead of the field's actual value.
For example, this is the email that is coming through:
First Name: [First Name]
Last Name: [Last Name]
Email: [Email Address]
Company Name: [Company Name]
Phone Number: [Phone Number]
I think it has to do with the Send Email editor using a rich text editor for the email template, but I've tried adjusting the message's HTML to no avail. This is what the markup looks like: (the <p> tags and labels used to be inline, but that didn't work either)
<p>First Name:
[<label id="{F49F9E49-626F-44DC-8921-023EE6D7948E}">First Name</label>]
</p>
<p>Last Name:
[<label id="{9CE3D48C-59A0-432F-B6F1-3AFD03687C94}">Last Name</label>]
</p>
<p>Email:
[<label id="{E382A37E-9DF5-4AFE-8780-17169E687805}">Email Address</label>]
</p>
<p>Company Name:
[<label id="{9C08AC2A-4128-47F8-A998-12309B381CCD}">Company Name</label>]
</p>
<p>Phone Number:
[<label id="{4B0C5FAC-A08A-4EF2-AD3E-2B7FDF25AFA7}">Phone Number</label>]
</p>
Does anyone know what could be going wrong?
I have encountered this issue before, but was using a custom email action. I managed to fix it by not using the deprecated methods in the SendMail class and instead using the
Sitecore.Form.Core.Pipelines.ProcessMessage namespace's ProcessMessage and ProcessMessageArgs classes.
My use case was a little more complicated than yours, as we were also attaching a PDF brochure to our message (which is why we were using the custom email action in the first place), but here is the code:
public class SendBrochureEmail : SendMail, ISaveAction, ISubmit
{
public new void Execute(ID formId, AdaptedResultList fields, params object[] data)
{
try
{
var formData = new NameValueCollection();
foreach (AdaptedControlResult acr in fields)
{
formData[acr.FieldName] = acr.Value;
}
var senderName = formData["Your Name"];
var emailTo = formData["Recipient Email"];
var recipientName = formData["Recipient Name"];
var documentTitle = formData["Document Title"];
if (documentTitle.IsNullOrEmpty())
{
documentTitle = String.Format("Documents_{0}", DateTime.Now.ToString("MMddyyyy"));
}
Subject = documentTitle;
if (!String.IsNullOrEmpty(emailTo))
{
BaseSession.FromName = senderName;
BaseSession.CatalogTitle = documentTitle;
BaseSession.ToName = recipientName;
var tempUploadPath = Sitecore.Configuration.Settings.GetSetting("TempPdfUploadPath");
var strPdfFilePath =
HttpContext.Current.Server.MapPath(tempUploadPath + Guid.NewGuid().ToString() + ".pdf");
//initialize object to hold WFFM mail/message arguments
var msgArgs = new ProcessMessageArgs(formId, fields, MessageType.Email);
var theDoc = PdfDocumentGenerator.BuildPdfDoc();
theDoc.Save(strPdfFilePath);
theDoc.Clear();
FileInfo fi = null;
FileStream stream = null;
if (File.Exists(strPdfFilePath))
{
fi = new FileInfo(strPdfFilePath);
stream = fi.OpenRead();
//attach the file with the name specified by the user
msgArgs.Attachments.Add(new Attachment(stream, documentTitle + ".pdf", "application/pdf"));
}
//get the email's "from" address setting
var fromEmail = String.Empty;
var fromEmailNode = Sitecore.Configuration.Factory.GetConfigNode(".//sc.variable[#name='fromEmail']");
if (fromEmailNode != null && fromEmailNode.Attributes != null)
{
fromEmail = fromEmailNode.Attributes["value"].Value;
}
//the body of the email, as configured in the "Edit" pane for the Save Action, in Sitecore
msgArgs.Mail.Append(base.Mail);
//The from address, with the sender's name (specified by the user) in the meta
msgArgs.From = senderName + "<" + fromEmail + ">";
msgArgs.Recipient = recipientName;
msgArgs.To.Append(emailTo);
msgArgs.Subject.Append(Subject);
msgArgs.Host = Sitecore.Configuration.Settings.MailServer;
msgArgs.Port = Sitecore.Configuration.Settings.MailServerPort;
msgArgs.IsBodyHtml = true;
//initialize the message using WFFM's built-in methods
var msg = new ProcessMessage();
msg.AddAttachments(msgArgs);
msg.BuildToFromRecipient(msgArgs);
//change links to be absolute instead of relative
msg.ExpandLinks(msgArgs);
msg.AddHostToItemLink(msgArgs);
msg.AddHostToMediaItem(msgArgs);
//replace the field tokens in the email body with the user-specified values
msg.ExpandTokens(msgArgs);
msg.SendEmail(msgArgs);
//no longer need the file or the stream - safe to close stream and delete delete it
if (fi != null && stream != null)
{
stream.Close();
fi.Delete();
}
}
else
{
Log.Error("Email To is empty", this);
throw new Exception("Email To is empty");
}
}
catch (Exception ex)
{
Log.Error("Test Failed.", ex, (object) ex);
throw;
}
finally
{
BrochureItems.BrochureItemIds = null;
}
}
public void Submit(ID formid, AdaptedResultList fields)
{
Execute(formid, fields);
}
public void OnLoad(bool isPostback, RenderFormArgs args)
{
}
}
It is very possible that the Email Action that WFFM ships with is using the deprecated methods, which could be your problem. I do not have time to look into it, but you can decompile the DLL and look to see what their Email Action is doing. Regardless, the above code should work out of the box, save for updating the fields to those that you are using and removing the code for attaching the PDF, should you choose to not have attachments.
Good luck, and happy coding :)
If you change a field on the form in any way (caption, name, type, etc) the link will change and you need to re-insert the placeholder and move it up to its location in your expected email. This is also true if you duplicate a form. You'll have to reinsert all the fields in the email or you will just get the outcome you show above.
Reinserting upon a change will ensure the value is collected!

NotesSession.GetDataBase method is returning null value

I have a c# class which was written to read the lotus emails for any attachments and save it to the local drive. It was working fine when I pass "" as first parameter to GetDataBase method and full path of .nsf file of my local system as second argument. But, if I remove "" and I specify my local system full name as first argument it is returning null value.
Is it problem with any permissions? If so, it should not work even when I pass "" as first parameter. Otherwise, should I have any other permissions at system/server level?
Please help me in this issue.
Finally, I could do it in the following way. And I thought of posting it to some one can atleast not to suffer again.
Following code is to read the attachment from the lotus emails and save it to the physical location.
string lotusServerName = ConfigurationSettings.AppSettings["Lotus_Server"].ToString();
string lotusDBFilePath = ConfigurationSettings.AppSettings["Lotus_DB_File_Path"].ToString();
string password = ConfigurationSettings.AppSettings["Password"].ToString();
string sourceFolder = ConfigurationSettings.AppSettings["Source_Folder"].ToString();
string targetFolder = ConfigurationSettings.AppSettings["Target_Folder"].ToString();
string documentsFolder = ConfigurationSettings.AppSettings["Documents_Folder"].ToString();
//Creating the notes session and passing password
NotesSession session = new NotesSession();
session.Initialize(password);
//Getting the DB instance by passing the servername and path of the mail file.
//third param "false" will try to check the DB availability by opening the connection
//if it cannot open, then it returns null.
NotesDatabase NotesDb = session.GetDatabase(lotusServerName, lotusDBFilePath, false);
//Get the view of the source folder
NotesView inbox = NotesDb.GetView(sourceFolder);
//looping through each email/document and looking for the attachments
//if any attachments found, saving them to the given specified location
//moving the read mails to the target folder
NotesDocument docInbox = null;
int docCnt = inbox.EntryCount;
for (int currDoc = 0; currDoc < docCnt; currDoc++) {
docInbox = inbox.GetFirstDocument();
object[] items = (object[])docInbox.Items;
foreach (NotesItem nItem in items) {
if (nItem.Name == "$FILE") {
NotesItem file = docInbox.GetFirstItem("$File");
string fileName = ((object[])nItem.Values)[0].ToString();
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.GetAttachment(fileName);
if (attachfile != null) {
attachfile.ExtractFile(documentsFolder + fileName);
}
}
}
docInbox.PutInFolder(targetFolder, true);//"true" creates the folder if it doesn't exists
docInbox.RemoveFromFolder(sourceFolder);
}
//releasing resources
if (session != null)
session = null;
if (NotesDb != null)
NotesDb = null;
if (inbox != null)
inbox = null;
if (docInbox != null)
docInbox = null;
Following is values read from .config file.
The above code will work properly if you alredy have lotus mail client in your system and you are able to access mails from your mail server. You don't require any other previliges.