Using SendGrid with script task in SSIS packages - c#

By using VS 2017, I created a SSIS package and then tried to utilize SendGrid with Script Task component but I kept have error messages. Error message is "Exception has been thrown by the target of an invocation." The following is my code and please help me look at what's wrong with it. Thank you.
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
static EmailAddress yao = new EmailAddress("user#sample.com", "User Sample");
static string template_id = "SendGridTemplateID";
static string _api_key = ConfigurationManager.AppSettings["SendGridKey"];
public void Main()
{
SendEmail().Wait();
Dts.TaskResult = (int)ScriptResults.Success;
}
static async Task SendEmail()
{
var client = new SendGridClient(_api_key);
var msg = new SendGridMessage();
msg.AddTo(new EmailAddress("Sample#user.com", "Sample User"));
msg.SetFrom(new EmailAddress("Sample#user.com", "Sample User"));
msg.SetTemplateData(GoogleLinkReport);
msg.SetTemplateId(template_id);
var response = await client.SendEmailAsync(msg);
Console.WriteLine(response.Body.ReadAsStringAsync().Result);
}
static GoogleLink GoogleLinkReport = new GoogleLink
{
header = "This is google link",
text = "Please click the button to open the link for google",
subject = "GoogleLink",
c2a_link = "https://www.google.com",
c2a_button = "Google Link"
};
public class GoogleLink
{
public string header;
public string text;
public string subject;
public string c2a_link;
public string c2a_button;
}
}

Related

How to attach HttpPostedFileBase file in aws ses email in C#

I am trying to attach a file in the AWS ses email. The file is being received by HttpPostedFileBase but the problem is I have no idea how can I use it to attach in a method called GetMessageBody() because body.Attachments.Add() only takes input for file location, not the HttpPostedFileBase file. Any idea how can I attach the file received by HttpPostedFileBase?
Use case:
[HttpPost, ValidateInput(false)]
public ActionResult SendHtmlEmailWithAttachment(HttpPostedFileBase file)
{
AWSEmailWithAttachment.SendAttachmentEmails("test#gmail.com", "noreply#test.co.uk", "my subject", file);
return Json("ok");
}
AWS ses email class:
public class AWSEmailWithAttachment
{
private static BodyBuilder GetMessageBody(HttpPostedFileBase attachment)
{
var body = new BodyBuilder()
{
HtmlBody = #"<p>Amazon SES Test body</p>",
TextBody = "Amazon SES Test body",
};
body.Attachments.Add(#"C:\Users\liaka\OneDrive\Desktop\attachment.txt");//I can use file location to attach with email but no idea how can i take file input form HttpPostedFileBase
return body;
}
private static MimeMessage GetMessage(string receiveraddress, string senderaddress, string subject, HttpPostedFileBase attachment)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Foo Bar", senderaddress));
message.To.Add(new MailboxAddress(string.Empty, receiveraddress));
message.Subject = subject;
message.Body = GetMessageBody(attachment).ToMessageBody();
return message;
}
private static MemoryStream GetMessageStream(string receiveraddress, string senderaddress, string subject, HttpPostedFileBase attachment)
{
var stream = new MemoryStream();
GetMessage(receiveraddress, senderaddress, subject, attachment).WriteTo(stream);
return stream;
}
public static void SendAttachmentEmails(string receiveraddress, string senderaddress, string subject, HttpPostedFileBase attachment)
{
var credentals = new BasicAWSCredentials(Credentials.AWS_Access_Key_ID, Credentials.AWS_Secret_Access_Key);
using (var client = new AmazonSimpleEmailServiceClient(credentals, RegionEndpoint.EUWest2))
{
var sendRequest = new SendRawEmailRequest { RawMessage = new RawMessage(GetMessageStream(receiveraddress, senderaddress, subject, attachment)) };
try
{
var response = client.SendRawEmail(sendRequest);
}
catch (Exception e) { }
}
}
}

How do you print MQTT messages to the console?

I have a very simple C# command line app that connects to an MQTT server and prints messages to the console.
using MQTTnet;
using MQTTnet.Client.Options;
using MQTTnet.Extensions.ManagedClient;
using System.Text;
var options = new MqttClientOptionsBuilder()
.WithTcpServer(MqttConfig.Server, MqttConfig.Port)
.WithCredentials(MqttConfig.User, MqttConfig.Password)
.WithClientId("MqttTest")
.WithCleanSession()
.Build();
var MqttClient = new MqttFactory().CreateMqttClient();
var cancellationToken = new CancellationToken();
var subscribeOptions = new MQTTnet.Client.Subscribing.MqttClientSubscribeOptions();
subscribeOptions.TopicFilters.Add(new MqttTopicFilter { Topic = MqttConfig.Topic });
MqttClient.ConnectAsync(options, cancellationToken);
MqttClient.SubscribeAsync(subscribeOptions, cancellationToken);
MqttClient.UseApplicationMessageReceivedHandler(e => { HandleMessageReceived(e.ApplicationMessage); });
while (true)
{
Task.Delay(1000).GetAwaiter().GetResult();
}
static void HandleMessageReceived(MqttApplicationMessage applicationMessage)
{
Console.WriteLine("### RECEIVED MESSAGE ###");
Console.WriteLine($"+ Topic = {applicationMessage.Topic}");
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(applicationMessage.Payload)}");
Console.WriteLine();
}
abstract class MqttConfig
{
public static readonly string Server = "servername";
public static readonly int Port = 1883;
public static readonly string User = "user";
public static readonly string Password = "password";
public static readonly string Topic = "#";
}
Putting the MqttConfig class information into an app like MQTT X shows a bunch of incoming messages. But running this C# app just shows a blank console.
I ended up making basing the application on an MQTTnet sample. I'm posting it as an answer here in case anyone else has the same question in the future.
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using System.Text.Json;
#region Subscribe to topic & handle incoming messages
var mqttFactory = new MqttFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithTcpServer(MqttConfig.Server, MqttConfig.Port)
.WithCredentials(MqttConfig.User, MqttConfig.Password)
.Build();
mqttClient.UseApplicationMessageReceivedHandler(e =>
{
Console.WriteLine("Received application message.");
e.DumpToConsole();
return Task.CompletedTask;
});
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(f => f.WithTopic(MqttConfig.Topic))
.Build();
await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
Console.WriteLine("MQTT client subscribed to topic.");
Console.ReadLine(); // Prevents app from immediately closing once MQTT subscription is complete.
// Will close if user presses "enter" before any messages are received.
}
static class ObjectExtensions
{
public static TObject DumpToConsole<TObject>(this TObject #object)
{
var output = "NULL";
if (#object != null)
{
output = JsonSerializer.Serialize(#object, new JsonSerializerOptions { WriteIndented = true });
}
Console.WriteLine($"[{#object?.GetType().Name}]:\r\n{output}");
return #object;
}
}
#endregion
static class MqttConfig
{
public static readonly string Server = "servername";
public static readonly int Port = 1883;
public static readonly string User = "user";
public static readonly string Password = "password";
public static readonly string Topic = "#";
}

Getting return type of Task (not Task<T>)

I use ASP.NET Identity 2.2.1.
I implement the interface IIdentityMessageService like this:
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
string body = ONMailStyles.getOpening();
body += message.Body;
Mail mailService = new Mail(message.Destination, message.Subject, body);
string succes = mailService.send();
return Task.FromResult(succes);
}
}
Below is (a part) of my Mail class:
public class Mail
{
public MailMessage message { get; set; }
public string send(string host, int port, string username, string wachtwoord, int timeout)
{
SmtpClient ss = new SmtpClient(host, port);
ss.EnableSsl = true;
ss.Timeout = timeout;
ss.DeliveryMethod = SmtpDeliveryMethod.Network;
ss.UseDefaultCredentials = false;
ss.Credentials = new System.Net.NetworkCredential(username, wachtwoord);
try
{
ss.Send(message);
message.Dispose();
return "succes";
}
catch (Exception ex)
{
return "no succes: " + ex.ToString();
}
}
}
In one of my controller's I have the following line:
var emailResult = UserManager.SendEmailAsync(user.Id, "Activeer uw lichtmeting account.", htmlMessage);
I get a result back of type Task. If I had await a like this I expected to get the string result of succes:
var emailResult = await UserManager.SendEmailAsync(user.Id, "Activeer uw lichtmeting account.", htmlMessage);
But I get the following compile error: "cannot assign void to an implicitly-typed variable". I just want to get the result of success in my controller. How do I accomplish that?
You could hide the interface method and create your own method to use from the outside:
public class EmailService : IIdentityMessageService
{
Task IIdentityMessageService.SendAsync(IdentityMessage message)
{
return this.SendAsync(message);
}
public Task<string> SendAsync(IdentityMessage message)
{
string body = ONMailStyles.getOpening();
body += message.Body;
Mail mailService = new Mail(message.Destination, message.Subject, body);
string succes = mailService.send();
return Task.FromResult(succes);
}
}
You don't have an await in your SendAsync method - is it actually calling anything asynchronously? Also if you want it to return a string you should make it return Task<string>, not Task. I'd try something along these lines.
public class EmailService : IIdentityMessageService
{
public async Task<string> SendAsync(IdentityMessage message)
{
string body = ONMailStyles.getOpening();
body += message.Body;
var mailService = new Mail(message.Destination, message.Subject, body);
string success = await mailService.send();
return success;
}
}

MVC 5: Cant send certain values in URL parameters

I am trying to send chars like : / . in asp.net mvc 5 to an API controller endpoint, but it fails as soon as I try something containing certain chars. For example, I can't send message:hi, I have to change it to message_hi to get it working.
I am trying to send an email using Exchange and the body (containing an URL and other info) won't go through.
My API Controller:
[Route("send/{adress}/{subject}/{body}")]
public void SendEmail(string adress, string subject, string body)
{
Office365MailSender ms = new Office365MailSender();
EmailDto email = new EmailDto(adress, subject, body);
ms.Send(email);
}
Calling the above endpoint from my application:
public static async Task<string> SendMail(IPhoneCall phoneCall)
{
var email = new EmailEntity(phoneCall);
using (var client = new HttpClient())
{
var uri = new Uri("http://url/email/send/" + email.Recipient + "/" + email.Title + "/" + email.body);
var msg = await client.GetAsync(uri);
}
return "Email Sent";
}
An example of a value of the uri variable would be:
http://url/email/send/myemail#outlook.com/Hello There/Hi,\nThis is a url you can use for stuff: https://thisisit.com. \n Thanks bye.
I've tried HttpUtility.UrlEncode on the body before I send it, but that does nothing. Does anyone know how to send strings containing these type of chars?
I would recommend you using the POST verb in order to send the body of the message. So you could start by writing a view model:
public class MailMessageViewModel
{
public string Address { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
that your Web API action will take as parameter:
[Route("send")]
[HttpPost]
public IHttpActionResult SendEmail(MyViewModel model)
{
Office365MailSender ms = new Office365MailSender();
EmailDto email = new EmailDto(model.Address, model.Subject, model.Body);
ms.Send(email);
return this.Ok();
}
and then you could invoke like this:
var email = new EmailEntity(phoneCall);
using (var client = new HttpClient())
{
var uri = new Uri("http://url/email/send");
var content = new StringContent(
JsonConvert.SerializeObject(new
{
Address = email.Recipient,
Subject = email.Title,
Body = email.body,
}),
UnicodeEncoding.UTF8,
"application/json");
var msg = await client.PostAsync(uri, content);
}

Amazon Product Advertising API Signing Issues

i am trying to search in amazon product database with the following code posted in amazon webservice sample codes page
AWSECommerceService ecs = new AWSECommerceService();
// Create ItemSearch wrapper
ItemSearch search = new ItemSearch();
search.AssociateTag = "ABC";
search.AWSAccessKeyId = "XYZ";
// Create a request object
ItemSearchRequest request = new ItemSearchRequest();
// Fill request object with request parameters
request.ResponseGroup = new string[] { "ItemAttributes" };
// Set SearchIndex and Keywords
request.SearchIndex = "All";
request.Keywords = "The Shawshank Redemption";
// Set the request on the search wrapper
search.Request = new ItemSearchRequest[] { request };
try
{
//Send the request and store the response
//in response
ItemSearchResponse response = ecs.ItemSearch(search);
gvRes.DataSource = response.Items;
}
catch (Exception ex)
{
divContent.InnerText = ex.Message;
}
and getting the following error
The request must contain the parameter
Signature.
and amazon documentation is not clear about how to sign the requests.
any idea how to make it work???
thx
i transcribed this vb code and it works for me
add the service reference and name it Amazon
http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl
go into the folder where your project is hosted, open the service reference folder and open the Reference.cs, then replace all the occurrences of [][] with [], next open AWSECommerceService.wsdl and find
<xs:element minOccurs="0" maxOccurs="unbounded" name="ImageSets">
and replace with
<xs:element minOccurs="0" maxOccurs="1" name="ImageSets">
add the following, and you'll need to manually reference some dlls
using System.Security.Cryptography;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Text.RegularExpressions;
using System.Xml;
using System.IO;
using System.Runtime.Serialization;
using AmazonApiTest.Amazon; //instead of AmazonApiTest use your project name
first various interface implementations
public class AmazonSigningMessageInspector : IClientMessageInspector
{
private string accessKeyId = "";
private string secretKey = "";
public AmazonSigningMessageInspector(string accessKeyId, string secretKey)
{
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
public Object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
string operation = Regex.Match(request.Headers.Action, "[^/]+$").ToString();
DateTime now = DateTime.UtcNow;
String timestamp = now.ToString("yyyy-MM-ddTHH:mm:ssZ");
String signMe = operation + timestamp;
Byte[] bytesToSign = Encoding.UTF8.GetBytes(signMe);
Byte[] secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
HMAC hmacSha256 = new HMACSHA256(secretKeyBytes);
Byte[] hashBytes = hmacSha256.ComputeHash(bytesToSign);
String signature = Convert.ToBase64String(hashBytes);
request.Headers.Add(new AmazonHeader("AWSAccessKeyId", accessKeyId));
request.Headers.Add(new AmazonHeader("Timestamp", timestamp));
request.Headers.Add(new AmazonHeader("Signature", signature));
return null;
}
void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message Message, Object correlationState)
{
}
}
public class AmazonSigningEndpointBehavior : IEndpointBehavior
{
private string accessKeyId = "";
private string secretKey = "";
public AmazonSigningEndpointBehavior(string accessKeyId, string secretKey)
{
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new AmazonSigningMessageInspector(accessKeyId, secretKey));
}
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatched)
{
}
public void Validate(ServiceEndpoint serviceEndpoint)
{
}
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParemeters)
{
}
}
public class AmazonHeader : MessageHeader
{
private string m_name;
private string value;
public AmazonHeader(string name, string value)
{
this.m_name = name;
this.value = value;
}
public override string Name
{
get { return m_name; }
}
public override string Namespace
{
get { return "http://security.amazonaws.com/doc/2007-01-01/"; }
}
protected override void OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, MessageVersion messageVersion)
{
writer.WriteString(value);
}
}
now you use the generated code in this way
ItemSearch search = new ItemSearch();
search.AssociateTag = "YOUR ASSOCIATE TAG";
search.AWSAccessKeyId = "YOUR AWS ACCESS KEY ID";
ItemSearchRequest req = new ItemSearchRequest();
req.ResponseGroup = new string[] { "ItemAttributes" };
req.SearchIndex = "Books";
req.Author = "Lansdale";
req.Availability = ItemSearchRequestAvailability.Available;
search.Request = new ItemSearchRequest[]{req};
Amazon.AWSECommerceServicePortTypeClient amzwc = new Amazon.AWSECommerceServicePortTypeClient();
amzwc.ChannelFactory.Endpoint.EndpointBehaviors.Add(new AmazonSigningEndpointBehavior("ACCESS KEY", "SECRET KEY"));
ItemSearchResponse resp = amzwc.ItemSearch(search);
foreach (Item item in resp.Items[0].Item)
Console.WriteLine(item.ItemAttributes.Author[0] + " - " + item.ItemAttributes.Title);
There's a helper class for REST called SignedRequestHelper.
You call it like so:
SignedRequestHelper helper =
new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
requestUrl = helper.Sign(querystring);
There must be a similar one for SOAP calls in the above links.
try this one.. i hope it'll help.. i try and it works.. please share it with others.
download the sample code on http://www.falconwebtech.com/post/Using-WCF-and-SOAP-to-Send-Amazon-Product-Advertising-API-Signed-Requests
we need to update service references, make little change at app.config, program.cs, and reference.cs.
app.config:
(1.) appSettings tag;
assign accessKeyId and secretKey value,
add .
(2.) behaviours tag -> endpointBehaviors tag -> behaviour tag -> signingBehavior tag;
assign accessKeyId and secretKey value.
(3.) bindings tag -> basicHttpBinding tag; (optional)
delete binding tag except AWSECommerceServiceBindingNoTransport
and AWSECommerceServiceBindingTransport.
(4.) client tag;
delete endpoint tag except AWSECommerceServiceBindingTransport.
program.cs:
add itemSearch.AssociateTag = ConfigurationManager.AppSettings["associateTag"]; before ItemSearchResponse response = amazonClient.ItemSearch(itemSearch);
reference.cs: (open file in service references folder using visual studio)
change private ImageSet[][] imageSetsField; to private ImageSet[] imageSetsField;
change public ImageSet[][] ImageSets {...} to public ImageSet[] ImageSets {...}
finally we can run our program and it will work. good luck..
nb: there will be 1 warning (invalid child element signing behaviour), i think we can ignore it, or if you have any solution please share.. ^^v..

Categories