How can I read the whole message using Gmail API - c#

I need all the text in the body for incoming email.
I tried:
var mesage = GetMessage(service, "me", 1);
Console.WriteLine(mesage.Snippet);
public static Message GetMessage(GmailService service, String userId, String messageId)
{
try
{
return service.Users.Messages.Get(userId, messageId).Execute();
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
return null;
}
But I am getting just snippet as shown in the screenshot.
Incoming mail to me:
Result:

Looking at the documentation, Message.Snippet only returns a short part of the message text. You should instead use Message.Raw, or more appropriately, Message.Payload.Body?
var message = GetMessage(service, "me", 1);
Console.WriteLine(message.Raw);
Console.WriteLine(message.Payload.Body.Data);
You should try both out and see what works best for what you're trying to do.
To get message.Raw you need to pass a parameter, as stated in the docs:
Returned in messages.get and drafts.get responses when the format=RAW parameter is supplied.
If none of those things work, you could try iterating over the parts of the message to find your data:
foreach (var part in message.Payload.Parts)
{
byte[] data = Convert.FromBase64String(part.Body.Data);
string decodedString = Encoding.UTF8.GetString(data);
Console.WriteLine(decodedString);
}

Related

gRPC: How to use dynamically typed values?

I'm trying using gRPC dynamically typed values but with the little information about their usefulness, It's almost impossible to do this... So I will show the image/code that I have problems and the questions that are eating my brain
gRPC Method I'm doing:
public override Task<HelloReply2> TestObject(Status request, ServerCallContext context) {
//The part I may have problems
var status = new Status();
//here I want a User that corresponds to my request.Data
//example -> request.Data = User1 (gives me null if User1 don`t exist in db)
// request.Data = 14 (gives me null if 14 don`t exist in db)
// request.Data = true (gives me null if true don`t exist in db)
var a1 = _context.Users_5.FirstOrDefault(x => x.Username.Equals(request.Data));
var b1 = _context.Users_5.FirstOrDefault(x => x.Email.Equals(request.Data));
var c1 = _context.Users_5.FirstOrDefault(x => x.Age.Equals(request.Data));
var d1 = _context.Users_5.FirstOrDefault(x => x.Test.Equals(request.Data));
//is a bool
//here i want too Create dynamic values
status.Data = Value.ForStruct(new Struct {
Fields =
{
["Integer"] = Value.ForNumber(c1!.Age),
["StringName"] = Value.ForString(a1!.Username),
["StringEmail"] = Value.ForString(b1!.Email),
["Boolean"] = Value.ForBool(d1!.Test)
}
});
//Below is just a simple string who gives different string (depending on the
//data Status (also how to read the message from the status.Data ?)
HelloReply2 hello = new();
if(a1 != null)
{
hello.Message = "There is a User with the Username " + request.Data + ". His Email is " + a1.Email;
} else if (b1 != null) {
hello.Message = "There is a User with the Email " + request.Data + ". His Username is " + b1.Username;
}
else if (c1 != null)
{
hello.Message = "There is at least one User with that Age of " + request.Data + ". His Username is " + c1.Username;
}
else if (d1 != null)
{
if(d1.Test == true)
{
hello.Message = "There is at least one User who dislikes chocolate: " + request.Data + ". His Username is " + d1.Username;
} else
{
hello.Message = hello.Message = "There is at least one User who likes chocolate: " + request.Data + ". His Username is " + d1.Username;
}
}
else
{
hello.Message = "We didn't find something with the value that the User put in. Value:" + request.Data;
}
return Task.FromResult(hello);
}
Questions: How to Get the one Value from my gRPC? How to convert a "Object" in c# (one string, one integer or one List) into a ONE value of google.protobuf.Value (so it not give me errors like this Controller from a Web Api below)? Is something wrong with my gRPC Service Method (is something wrong reading the dynamic values? Can I do that calls for getting a User for a DB? How to read dynamic values?)
// I try using Google.Protobuf.WellKnownTypes.Value obj but
//not workings because gives me a lot of values to put
[HttpGet("TypeObject/{obj}")]
public async Task<ActionResult<HelloReply2>> TypeObject([FromRoute] Object obj){
Status objRequest = new Status { Data = (Google.Protobuf.WellKnownTypes.Value)
obj };
//cannot do this (gives me error of casting but the ideia is doing something
//similar to this)
var hello = await _greetClient.TestObjectAsync(objRequest);
return Ok(hello);
}
Any help on how to resolve this error of using Value gRPC or if is something wrong with the code is always welcome.
Edit:
One day after this question I don't have any solutions / progress. I was think of doing Any or OneOf for testing but it also gives me errors (who don't make sense at all). This code from Microsoft (C# Format part is not recognize) doesn't work in my project with the protos reload (the problem is not in the protos)
Link: https://learn.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/protobuf-any-oneof
How I can use Any / OneOf without give me error in the Formating? What is the difference between Value and this two? Can the three (Value, Any, OneOf) be dynamic/Object values (if yes how to convert the types)?
Edit 2:
Still have problems, I'm trying using gRPC Any , and maybe have some progress (not all).
So with Any I have my method in the server gRPC and it is like this
public override Task<HelloReply2> TestObject3(AnyMessage request, ServerCallContext context){
HelloReply2 anyMessageResponse;
var y = request.TypeUrl;
switch (request.TypeUrl)
{
case "type.googleapis.com/any.HelloRequest":
var string_1 = request.Unpack<HelloRequest>();
anyMessageResponse = new HelloReply2{
Message = "You type String: " + $"{string_1.Name}"
};
break;
case "type.googleapis.com/any.TestInteger1":
var integer_1 = request.Unpack<TestInteger1>();
anyMessageResponse = new HelloReply2{
Message = "You type Integer: " + $"{integer_1.Message}"
};
break;
case "type.googleapis.com/any.TestBool1":
var bool_1 = request.Unpack<TestInteger1>();
anyMessageResponse = new HelloReply2{
Message = "You type Bool: " + $"{bool_1.Message}"
};
break;
default:
throw new InvalidOperationException("Unexpected type URL.");}
return Task.FromResult(anyMessageResponse);
}
This ideia comes from here (https://github.com/grpc/grpc-dotnet/issues/917), but the client part their don't have any much info or I don't understand that part
This is what I did in the WebApi (who is my client and the code is similar to the above one)
using AnyMessage = Google.Protobuf.WellKnownTypes.Any;
[HttpGet("TypeObject3/{obj3}")]
public async Task<ActionResult<HelloReply2>> TypeObject3([FromRoute] string obj3)
{
AnyMessage objRequest = new() { TypeUrl = obj3 };
var hello = await _greetClient.TestObject3Async(objRequest);
var l = hello.Message;
return Ok(hello);
}
First I had the variable Any declared in the method instead of string but as you can only put string and stringBytes so I preferred to put it like this (with the string as an obj3 variable) but my goal is to see if the variable is of type TestBool1 or TestInteger1 as I have declared in the protos and not be a string that I will be able to see, and the biggest problem was if I had more variables inside the messages how to proceed? So my secondary question is how to use Any on the client side via the Web-Api? I forgot to say but I'm using .Net 6 Core and for testing I'm using Swagger, where at this moment my error hits the Exception dictated by the Server method.
Questions: Why TypeUrl is a string and not object? How to fix my problem? How to test the object type (or string) for more values if the messages was with 1 more types?
Also I will show my test proto too show how I'm doing this
import "google/protobuf/struct.proto";
import "google/protobuf/any.proto";
package greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayNormalHello (Empty_2) returns (HelloReply);
rpc SayHello (HelloRequest) returns (HelloReply2);
rpc TestInt (TestInteger1) returns (HelloReply2);
rpc TestBoolean (TestBool1) returns (HelloReply2);
rpc TestObject (Status) returns (HelloReply2); //Not working
rpc TestObject2 (Status2) returns (HelloReply2); //Not working
rpc TestObject3 (google.protobuf.Any) returns (HelloReply2); //Also
//Not working
}
message Empty_2{
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
// The response message containing the greetings.
message HelloReply2 {
string message = 1;
}
message TestInteger1 {
int32 message = 1;
}
message TestBool1 {
bool message = 1;
}
message Status {
google.protobuf.Value data = 1;
}
message Status2 {
google.protobuf.Any data = 1;
}
Any help is welcome.
In the project I developed, I needed an infrastructure where I could perform dynamic operations such as REST service using gRPC. As I understand it, what you want is something similar to this.
I have developed a solution for this. It might work for you too.
You can gain some flexibility by making a definition with a single String field for Requests and Responses that you want to be Dynamic, and then using this field to hold JSON data as strings.
For example, instead of defining different responses for different types, you can solve it by making one definition like this.
message HelloReply {
// Stringified JSON Data
string data = 1;
}

Parse an email address string in C# to MailAddress object

I have a C# backend code that receives a POST request from the client side code in TypeScript.
The JSON is done for the POST with JSON.stringify(objectOfData);
In the C# code I am getting an exception when I try to use the object like so:
// Passed into this function is InboundObjectDTO inboundObject
// inboundObject.Email in debugger is like so: "\"a#example.com\""
var message = new MailMessageDTO
{
Subject = "My Subject",
MailAddresses = new List<MailAddress>()
};
message.MailAddresses.Add(new MailAddress(inboundObject.Email));
Am I supposed to deserialize the object somehow before hand? I have 3 strings in the object: email, message, and name.
The last line of code above gives me "An invalid character in MailAddresses exception." I am guessing it needs to have all the extra quotes and such removed in a proper way.
As OP had originally postulated, the issue is the quotes around the email address, all we need to do is remove those quotes. This process is referred to as Sanitizing the input.
The original methodology was hard to follow and the exception information posted was ambiguous, this solution shows how to sanitise the input and return more relevant information with the exception.
The example you have pasted ""a#example.com"" would not fail in your original code that included the santize logic, if you had simply used the result of the sanitize step!
You should wrap the code block in a try-catch so you can capture the exception and output the specific string value that has failed:
string email = inboundObject.Email;
MailMessageDTO message = null;
try
{
// sanitized the email, removed known invalid characters
email = email.Replace("\"", "");
// construct the payload object
message = new MailMessageDTO
{
Subject = "My Subject",
MailAddresses = new List<MailAddress>()
};
message.MailAddresses.Add(new MailAddress(email));
}
catch (Exception ex)
{
throw new ApplicationException($"Failed to construct MailMessage for email: {email}", ex);
}
Now when this fails, we have more information to work with inside the exception, infact this situation itself probably warrants it's own separate reusable method:
public MailAddress SanitizeEmail(string emailAddress)
{
string email = emailAddress;
try
{
// sanitized the email, removed known invalid characters
email = email.Replace("\"", "");
// TODO: add other rules an replacement cases as you find them
return new MailAddress(email);
}
catch (Exception ex)
{
throw new ApplicationException($"Failed to sanitize email address: '{email}' [original input: '{emailAddress ?? "NULL" }']", ex);
}
}
You could call this using:
message.MailAddresses.Add(SanitizeEmail(email));
Update
OP's original code included references and test conditions that are no longer in the posted code, this response has only been marginally updated to reflect those changes
If you are posting json data to controller action,you can use [FromBody],[FromBody] will get values from the request body:
public IActionResult Index([FromBody]inboundObject inboundObject)
{
...
}
Or you can use JsonConvert.DeserializeObject to deserialize the the JSON to specified .NET type:
message.MailAddresses.Add(new MailAddress(JsonConvert.DeserializeObject<string>(inboundObject.Email)));

How can i interate on Fulfillment Messages to return message by message to client

I'm using Dialogflow to integrate on Microsoft Bot Framework, when i use FulfillmentText, my code works fine, but i need to use FulfillmentMessages because i have many messages returning on my code, i tried this code, but "retorno" variable receive json format return, how can i interate to all messages returning line by line to response for my client?
foreach (Intent.Types.Message msg in queryResult.FulfillmentMessages)
{
retorno = msg.Text;
Console.WriteLine($"Fulfillment text: {retorno}");
}
Do you have any sample using Microsoft Bot Framework and Google.Cloud.Dialogflow.V2 API?
I created a array of IActivity and used foreach at each messages adding text by text to "respostas" array.
Finally i used "await turnContext.SendActivitiesAsync(retorno, cancellationToken);" because i can pass array of IActivity:
IActivity[] respostas;
respostas = new IActivity[1];
int cnt = 0;
foreach (Intent.Types.Message msg in queryResult.FulfillmentMessages)
{
foreach (string msgstr in msg.Text.Text_)
{
retorno = retorno + msgstr.ToString() + "\r\n";
respostas[cnt] = MessageFactory.Text(msgstr.ToString(), msgstr.ToString());
cnt++;
}
Console.WriteLine($"Fulfillment text: {retorno}");
}
await turnContext.SendActivitiesAsync(retorno, cancellationToken);
This code works fine for my objectives.

How to retrieve email based on time in Google api using c#?

How to retrieve email based on time in Google api using c#?
Can we pass date time to query string for getting the latest email?
While working around this one i am able to find pas the date only.
Is there any way to get the latest mail based on time?
Yes, you can achieve this by passing in a query parameter along with Get Message List call of Gmail API like below:
List<Message> result = new List<Message>();
UsersResource.MessagesResource.ListRequest request = service.Users.Messages.List(userId);
request.Q = query;//This is where you put in your data query
do
{
try
{
ListMessagesResponse response = request.Execute();
result.AddRange(response.Messages);
request.PageToken = response.NextPageToken;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
} while (!String.IsNullOrEmpty(request.PageToken));
Query parameter is the same as you pass in your mailbox search box. e.g. after:2015/6/28 before:2015/7/1
Afterwards, fetch individual message details by calling Get with message ID.
Hope this helps.
Furhan's answer is great. I would just like to add, that if you want to search for mails more specifically than 2015/6/28, you can supply e.g. after:<TIME_IN_SECONDS_SINCE_EPOCH>
Let's say you wanted mail after:2015/6/28 12:55:00 and before:2015/7/1 02:30:00, your would write:
after:1435496100 before:1435710600

How to check whether a facebook user liked my facebook page or not using ASP.Net

I want to check whether a facebook user liked my facebook page or not. I got so many solutions using javascript but I want to implement this requirement in ASP.Net.
I copied the code from the below link:
http://duanedawnrae.com/Blog/post/2012/02/29/Determine-if-a-Facebook-user-Likes-your-page-with-ASPNET.aspx
I got the below ASP.Net code which works for the same.
ASP.Net code:
public class WebService : System.Web.Services.WebService
{
[WebMethod()]
public string GetFacebookLikeStatus(string fbpageid, string fbappid, string fbtoken, string fburl)
{
string strReturn = null;
// Placeholder for the Facbook "like" API call
string strURL = null;
strURL = "https://graph.facebook.com/me/likes?access_token=" + fbtoken;
// Placeholder for the Facebook GET response
WebRequest objGETURL = null;
objGETURL = WebRequest.Create(strURL);
// Declare response stream
Stream objStream = null;
// Declare The Facebook response
string strLine = null;
// Declare a count on the search term
int intStr = 0;
try
{
// Create an instance of the StreamReader
StreamReader objReader = new StreamReader(objStream);
// Get the response from the Facebook API as a JSON string.
// If access_token is not correct for the logged
// on user Facebook returns (400) bad request error
objStream = objGETURL.GetResponse().GetResponseStream();
// If all is well
try
{
// Execute the StreamReader
strLine = objReader.ReadToEnd().ToString();
// Check if Facebook page Id exists or not
intStr = strLine.IndexOf(fbpageid); // if valid return a value
if (intStr > 0)
{
strReturn = "1";
// if not valid return a value
}
else
{
strReturn = "0";
}
objStream.Dispose();
}
catch (Exception ex)
{
// For testing comment out for production
strReturn = ex.ToString();
// Uncomment below for production
//strReturn = "Some friendly error message"
}
}
catch (Exception ex)
{
// For testing comment out for production
strReturn = ex.ToString();
// Uncomment below for production
//strReturn = "Some friendly error message"
}
return strReturn;
}
}
The above code contains a webservice which contains a single function. The function contains four input parameters and returns a single output string.
But when I run this webservice I got the error, “Value cannot be null. Parameter name: stream”. This error is coming because the “objStream” variable is set to null. Please fix the issue so that I can get my correct output as I dont know how to implement my requirement.
Like Gating is not allowed on Facebook, and neither is incentivizing users to like your Page. Users must like something only because they really want to, you can´t reward them in any way.
That being said, you would need the user_likes permission to use /me/likes, and you would need to get it approved by Facebook. Which will not happen just for checking if the user liked your Page.
Btw, that article is from 2012. A lot of stuff changed since then.

Categories