How to create an ad-hoc email and send it using Acumatica - erp

In Acumatica you can use notifications to automate some emails.
In my scenario, we are creating a process that will at non-specific (non-set) times need to send an email when a specific condition is triggered, such as an employee needs to know they need to do something.
We are building this logic into the system and I am looking for a code sample of how to send the email when this happens.
We will be using an email template, but need to accomplish the feat in code.
I would hope there should be some kind of acumatica email class where we could just call it and pass the required info something like:
PX.Common.email.Send(params)...
Any example code would be appreciated.

It turns out that there is a KB article that gives an example of how to do this.
for our scenario, Here is a more recent version of the code that has been verified to send an email using either of 2 email templates.
private void mSendEmail(string toEmail, int? emailTemplateID, long? noteid, string source, string toDisplayName)
{
bool sent = false;
string sError = "Failed to send E-mail.";
POOrder porec = poOrder.Select(noteid);
EPExpenseClaim eprec = epExpense.Select(noteid);
try
{
Notification rowNotification = PXSelect<Notification,
Where<Notification.notificationID, Equal<Required<Notification.notificationID>>>>.Select(this, emailTemplateID);
if (rowNotification == null)
throw new PXException(PXMessages.Localize("Notification Template for Escalation is not specified."));
if (String.IsNullOrEmpty(toEmail))
throw new PXException(PXMessages.Localize("E-mail is not specified for Escalation Employee. Name=[" + toDisplayName +"]"));
if (source == "PO")
{
var sender = TemplateNotificationGenerator.Create(porec, rowNotification.NotificationID.Value);
sender.MailAccountId = rowNotification.NFrom.HasValue ?
rowNotification.NFrom.Value :
PX.Data.EP.MailAccountManager.DefaultMailAccountID;
sender.To = toEmail;
IEnumerable<EPActivity> epActivityArray = sender.Send();
if (epActivityArray.Count() > 0)
{ sent = true; }
}
if (source == "EP")
{
var sender = TemplateNotificationGenerator.Create(eprec, rowNotification.NotificationID.Value);
sender.MailAccountId = rowNotification.NFrom.HasValue ?
rowNotification.NFrom.Value :
PX.Data.EP.MailAccountManager.DefaultMailAccountID;
sender.To = toEmail;
IEnumerable<EPActivity> epActivityArray = sender.Send();
if (epActivityArray.Count() > 0)
{ sent = true; }
}
}
catch (Exception Err)
{
sent = false;
sError = Err.Message;
}
if (!sent)
throw new PXException(PXMessages.Localize(sError));
}

Here I want to present shorter version of sending email:
using PX.Objects.EP;
using PX.Data.EP;
**...**
var sender = new NotificationGenerator
{
To = "someone#example.com",
Subject = $"Subject information {DateTime.Now:d}",
Body = "Body of message",
BodyFormat = EmailFormatListAttribute.Text
};
sender.Send();

Related

how to get date wise email faster using gmail API in Asp.Net MVC with OAuth Token

Here I have written code for Gmail API to fetch mail with date filter
I am able to fetch MessageId and ThreadId using the First API. On the basis of MessageId, I put that messageId parameter in a List object and I have sent this parameter in foreach loop from List to the next API to fetch email body on basis of messageID. But the process is very slow for fetching messages from Gmail
public async Task<ActionResult> DisplayEmailWithFilter (string fromDate, string toDate) {
Message messageObj = new Message ();
Example exampleObj = new Example ();
List<GmailMessage> gmailMessagesList = new List<GmailMessage> ();
GmailMessage gmailMessage = new GmailMessage ();
var responseData = "";
//dateFilter string parameter Created with Date Values
string dateFilter = "in:Inbox after:" + fromDate + " before:" + toDate;
try {
// calling Gmail API to get MessageID Details by Date Filter
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue (scheme: "Bearer",
parameter : Session["Token"].ToString ());
HttpResponseMessage responseMessage = await client.GetAsync ("https://www.googleapis.com/gmail/v1/users/me/messages?q=" + dateFilter);
if (responseMessage.IsSuccessStatusCode) {
var data = responseMessage.Content;
}
try {
responseData = responseMessage.Content.ReadAsStringAsync ().Result;
//This Json Data Converted into List Object
var msgList = JsonConvert.DeserializeObject<Root1> (responseData);
//loop for Fetching EmailMessageData by MessageID
if (msgList.resultSizeEstimate != 0) {
foreach (var msgItem in msgList.messages) {
messageObj.id = msgItem.id;
//Calling API with MessageID Parameter to fetch Respective Message Data
HttpResponseMessage responseMessageList = await client.GetAsync ("https://www.googleapis.com/gmail/v1/users/userId/messages/id?id=" + messageObj.id.ToString () + "&userId=me&format=full");
if (responseMessageList.IsSuccessStatusCode) {
var dataNew = responseMessageList.Content;
var responseDataNew = responseMessageList.Content.ReadAsStringAsync ().Result;
//Converting json string in Object
exampleObj = JsonConvert.DeserializeObject<Example> (responseDataNew);
gmailMessage.Body = exampleObj.snippet;
//fetching Header Values comparing with string to get Data
for (int i = 1; i < exampleObj.payload.headers.Count; i++) {
if (exampleObj.payload.headers[i].name.ToString () == "Date") {
gmailMessage.RecievedDate = exampleObj.payload.headers[i].value;
}
if (exampleObj.payload.headers[i].name.ToString () == "Subject") {
gmailMessage.Subject = exampleObj.payload.headers[i].value;
}
if (exampleObj.payload.headers[i].name.ToString () == "Message-ID") {
gmailMessage.SenderEmailID = exampleObj.payload.headers[i].value;
}
if (exampleObj.payload.headers[i].name.ToString () == "From") {
gmailMessage.SenderName = exampleObj.payload.headers[i].value;
}
}
//Adding This Object Values in GmailMessgage List Object
gmailMessagesList.Add (
new GmailMessage {
Body = exampleObj.snippet,
SenderEmailID = gmailMessage.SenderEmailID,
RecievedDate = gmailMessage.RecievedDate,
SenderName = gmailMessage.SenderName,
Subject = gmailMessage.Subject,
});
}
}
}
} catch (Exception e) {
string errorMgs = e.Message.ToString ();
throw;
}
} catch (Exception e) {
string errorMgs = e.Message.ToString ();
throw;
}
return View (gmailMessagesList);
}
I can fetch Gmail email datewise but it took so much time to fetch. how can I improve my code and performance faster?
The query seems like the most you can do. If you know more information about those emails, like a specific subjects or there always come from the same sender you can try to filter that too, like you would in the Gmail interface.
Other way you would be kind of out of luck. You are limited by the files retrieved from User.messages.list.
If you need to escape from the API limitations maybe trying to retrieve the message other way would be the correct way to go. Considerate creating a small code to retrieve message by the IMAP protocol. Several questions in this topic may help you:
Reading Gmail messages using Python IMAP
Reading Gmail Email in Python
How can I get an email message's text content using Python?

asp.net mvc 5 sent email attachments are damaged

I am trying to send an email using the method described in this tutorial with a model structure form this tutorial and im partially successfull in doing so. The only issue I am having is the fact that files sent as attachments are damaged. I have tried to get it working in so many ways that I lost count. Obviously haven't been trying hard enough since I didn't find the answer, but decided to ask while I continue looking for an answer.
My controller action is as follows:
public async Task<ActionResult> Index( [Bind(Include = "column names..")] Contact contact, HttpPostedFileBase upload){
if (ModelState.IsValid && status)
{
var message = new MailMessage();
if (upload != null && upload.ContentLength > 0)
{
// 4MB -> 4000 * 1024
const int maxFileSize = 4096000;
if (upload.ContentLength < maxFileSize)
{
var document = new File
{
FileName = System.IO.Path.GetFileName(upload.FileName),
FileType = FileType.Document,
ContentType = upload.ContentType
};
var supportedTypes = new[] {"doc", "docx", "pdf", "jpg"};
var extension = System.IO.Path.GetExtension(document.FileName);
if (extension != null)
{
var fileExt = extension.Substring(1);
if (!supportedTypes.Contains(fileExt))
{
ModelState.AddModelError("document", "Wrong format");
return View();
}
//this is the line that sends damaged attachments,
//I believe I should be using document in some way (using reader bit below),
//but whatever I use the code complains or crashes.
message.Attachments.Add(new Attachment(upload.InputStream, Path.GetFileName(upload.FileName)));
using (var reader = new System.IO.BinaryReader(upload.InputStream))
{
document.Content = reader.ReadBytes(upload.ContentLength);
//message.Attachments.Add(new Attachment(document.Content, document.FileName));
}
contact.Files = new List<File> {document};
}
}else
{
ModelState.AddModelError("document", "File too big. Max 4MB.");
}
}
EDIT: A lot of times the code cannot find the file, how do I make sure I give it correct path each time?

How we can show "No Data Available" message in RDLC Reports via Resources files

How we can show "No Data Available" message in RDLC Reports via Resources files if no data is found. Currently we are reflecting message from NoRowsMessage property for a table, matrix, or list
(https://technet.microsoft.com/en-us/library/cc645968.aspx).
But we want to show it via Resource files and C# code rather then setting it from Properties of Table. Can anyone please assist. The code (Page_Load) of our control page (.ascx)is mentioned below:
private void Page_Load(object sender, EventArgs e)
{
var presenter = (ReportPresenter)Model;
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.Visible = true;
var rdlcPath = "~/ReportsRDLC/EmployeeData.rdlc";
if(presenter.ReportFilter.GroupOption == Resources.Date)
{
rdlcPath = "~/ReportsRDLC/EmployeeDatebyDate.rdlc";
}
groupOption.SelectedValue = presenter.ReportFilter.GroupOption;
const string DataSetName = "EmployeeDataSet";
reportViewer.LocalReport.ReportPath = HttpContext.Current.Server.MapPath(rdlcPath);
var dataSource = new ReportDataSource(DataSetName, presenter.EmployeeDetails);
reportViewer.AsyncRendering = false;
reportViewer.SizeToReportContent = true;
reportViewer.ShowPrintButton = false;
reportViewer.ShowRefreshButton = false;
reportViewer.ShowToolBar = true;
reportViewer.Height = 600;
reportViewer.Width = 400;
reportViewer.ShowPageNavigationControls = false;
reportViewer.ShowFindControls = false;
reportViewer.ShowZoomControl = false;
reportViewer.LocalReport.DataSources.Add(dataSource);
}
Perhaps you could send the message as a parameter.
You can tell if the report will be empty depending if presenter.EmployeeDetails is empty.
ReportParameter[] myParameters = new ReportParameter[1];
myParameters[0] = new ReportParameter("pEmptyMessage", presenter.EmployeeDetails.Any() ? "No Data Available" : string.Empty);
reportViewer.LocalReport.SetParameters(myParameters);
On your report you can then display this message as you please, using the parameter. You can even place it in a textbox and decide whether to display it based on the value.
I hope this is of use to you.
Edit: I forgot to mention that you should add the report parameter with the correct name to your reporter:
In the reporter you can then use the parameter as followed : [#pEmptyMessage]
=Parameters!pEmptyMessage.Value

RequestContext.Principal.Identity.Name is empty in web api 2 post

I'm new to web api and I seem to be having an issue with getting the name of the signed in user inside of my post method. Im using
RequestContext.Principal.Identity.Name
However, this only seems to be returning an empty string. It works fine in my get method, but not in the post. Here's my entire method
[Route("receive")]
[HttpPost]
public HttpResponseMessage Receive(PostmarkInboundMessage message)
{
if (message != null)
{
// To access message data
var headers = message.Headers ?? new List<Header>();
// To access Attachments
if (message.Attachments != null)
{
var attachments = message.Attachments;
var c = new CVService();
var user = string.IsNullOrEmpty(RequestContext.Principal.Identity.Name) ? "unknown" : RequestContext.Principal.Identity.Name;
c.UpdateLog(user);
foreach (var attachment in attachments)
{
// Access normal members, etc
var attachmentName = attachment.Name;
// To access file data and save to c:\temp\
//if (Convert.ToInt32(attachment.ContentLength) > 0)
//{
// byte[] filebytes = Convert.FromBase64String(attachment.Content);
// var fs = new FileStream(attachmentSaveFolder + attachment.Name,
// FileMode.CreateNew,
// FileAccess.Write,
// FileShare.None);
// fs.Write(filebytes, 0, filebytes.Length);
// fs.Close();
//}
}
}
// If we succesfully received a hook, let the call know
return new HttpResponseMessage(HttpStatusCode.Created); // 201 Created
}
else
{
// If our message was null, we throw an exception
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent("Error parsing Inbound Message.") });
}
}
Any help will be greatly appreciated.
Be sure you send the header (token) in both methods GET and POST and also, set the [Authorize] filter in both methods or the controller itself so you will be rejected if the token is not being send

Not able to retrieve messages from topic using EMS.NET API

I am trying to write a simple application to send messages to a topic from use input and show messages published on topic.
There are two command line executables - one for publisher and another for subscriber.
When I publish messages on a topic, I can see the messages getting submitted to the topic.
The following command shows that there are messages on the topic (see F1.gif):-
show stat EMS.Test.Topic
The following command shows that the messages are getting consumed by the subscribers (see F2.gif)
show stat consumers topic=EMS.Test.Topic
However, I am not able to retrieve messages the EMS .NET API. It gets stuck on Message msg = subscriber.Receive();. I made sure the connection details and authentication details are correct because they are used when publishing the messages.
public string ReceiveMessagesFromTopic(string topicName)
{
TopicConnection connection = null;
string messageFromPublisher = string.Empty;
try
{
var factory = new TIBCO.EMS.TopicConnectionFactory(serverUrl);
connection = factory.CreateTopicConnection(userName, password);
TopicSession session = connection.CreateTopicSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.CreateTopic(topicName);
TopicSubscriber subscriber = session.CreateSubscriber(topic);
connection.Start();
while (true)
{
Message msg = subscriber.Receive();
if (msg == null)
{
break;
}
if (msg is TextMessage)
{
TextMessage tm = (TextMessage) msg;
messageFromPublisher = tm.Text;
}
}
connection.Close();
}
catch (EMSException e)
{
if (connection!=null)
{
connection.Close();
}
throw;
}
return messageFromPublisher;
}
There was a silly mistake in my .NET code. the following while loop never returns so there is no return. I need to break the while loop when I get a message. Duh!!!!
while (true)
{
Message msg = subscriber.Receive();
if (msg == null)
{
break;
}
if (msg is TextMessage)
{
TextMessage tm = (TextMessage) msg;
messageFromPublisher = tm.Text;
break;
}
}

Resources