C# System.Net.Sockets.SocketException - c#

I'm trying to make URLReader public string, to not dublicate it in every function. So i have something like this:
public static string URLReader(string url)
{
try
{
WebClient webClient = new WebClient();
Stream fileStream = webClient.OpenRead(url);
using (StreamReader reader = new StreamReader(fileStream))
{
return reader.ReadToEnd();
}
}
catch
{
MessageBox.Show("URL Not exists or you are not connected to internet!", "Problems!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return "";
}
}
I don't know why, but catch not working.. For example, if I write incorrect url, or disconnect from internet it must print for me that "URL Not exists or you are not connected to interned!" But I've give error in this line:
Stream fileStream = webClient.OpenRead(url);
Error:
The first stage of processing exceptions of type
"System.Net.Sockets.SocketException" in System.dll
For more information: The requested name is correct, but the data requested type was found
If this exception handler is available, the program can be continued safely.
P.S Error mesage translated by google translate, because I'm not english
Thanks in advance.

Related

Cast Amazon SES emails, stored in S3 buckets, to MimeMessage type (MimeKit)

I need to read incoming email messages, with the following constraints:
An Amazon SES rule stores the incoming emails to a S3 bucket;
These emails then need to be cast to the MimeMessage type, of the MimeKit C# library, in order to work well with legacy code.
Thing is when I try to convert the emails to the MimeMessage, I get the exception "The filename, directory name or volume label syntax is incorrect."
How can I make the conversion to MimeMessage work? Should I parse the contents of the email messages with Regex for it?
I know I could integrate Amazon SES with Amazon WorkMail to receive my messages in the Mime format, which would make it easier for me. But I would avoid having to subscribe to another paid service from Amazon if I could.
I post below both my code and the message error, to better illustrate the problem:
public GetMailController(AmazonS3Client s3Client, IConfiguration configuration)
{
_s3Client = s3Client;
_config = configuration;
}
[HttpGet(Name = "Get")]
public IEnumerable<MimeMessage> Get()
{
string AwsS3Bucket = _config.GetValue<string>("AwsS3Bucket");
List<MimeMessage> mails = new();
List<string> bucketKeys = GetBucketIds();
foreach (string k in bucketKeys)
{
GetObjectResponse response = _s3Client.GetObjectAsync(new GetObjectRequest() { BucketName = AwsS3Bucket, Key = k }).GetAwaiter().GetResult();
using (Stream responseStream = response.ResponseStream)
using (StreamReader reader = new StreamReader(responseStream))
{
string content = reader.ReadToEnd();
try
{
var mail = MimeMessage.LoadAsync(content).GetAwaiter().GetResult(); // Exception: "The filename, directory name or volume label syntax is incorrect."
mails.Add(mail);
}
catch (Exception exc)
{
return null;
}
}
}
return mails;
}
Resulting error message
The filename, directory name or volume label syntax is incorrect.
I tried using the MimeKit method MimeMessage.Load() to parse a email message in MIME format, but insted got an exception: The filename, directory name or volume label syntax is incorrect.
The MimeMessage.Load() method expects to receive either a filename (file path) or a stream as an argument.
Since you're providing it with the string-equivalent of the stream, it thinks you're providing it a file name - hence the filename, directory name or volume label syntax is incorrect error.
Directly use the stream you get from the GetObjectResponse, like so:
GetObjectResponse response = _s3Client.GetObjectAsync(new GetObjectRequest() { BucketName = AwsS3Bucket, Key = k }).GetAwaiter().GetResult();
using (Stream responseStream = response.ResponseStream)
{
try
{
var mail = MimeMessage.Load(responseStream);
mails.Add(mail);
}
catch (Exception exc)
{
return null;
}
}
I would also recommend to use await instead of .GetAwaiter().GetResult().

File.Create and File.OpenWrite does not release the file even if it's closed and also disposed

I am downloading a pdf file using HttpWebRequest object and write the content directly to a FileStream from a response stream, using all "using" blocks and also the .Close method right after the data is copied.
And the next step, I need to extract some text from that pdf file by using some 3rd party library (iText7) but it can't access the file.
At first, I thought it was the iText7-related issue but then I realized it doesn't seem so because I can't even delete the file from file explorer, getting "file in use" error by my own app.
Here's the sample code:
HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(url);
webReq.AllowAutoRedirect = true;
webReq.CookieContainer = Cookies;
webReq.UserAgent = UserAgent;
webReq.Referer = Referrer;
webReq.Method = WebRequestMethods.Http.Get;
using (HttpWebResponse response = (HttpWebResponse)webReq.GetResponse())
{
using (Stream httpResponseStream = response.GetResponseStream())
{
using (FileStream output = File.Create(file1))
{
httpResponseStream.CopyTo(output);
output.Close();
}
httpResponseStream.Close();
response.Close();
Cookies = webReq.CookieContainer;
}
}
GC.Collect();
ExtractPDFDoc(file1);//error throws in this function and the exception.message is "Cannot open document."
Console.WriteLine("now waiting to let you check the file is in use? try delete it manually...");
Console.ReadKey(); //added this line to ensure that file is actually in use. I can't even delete the file manually from windows file explorer at this time. But, interestingly, Acrobat Reader can OPEN the file when I double click, which makes me thing that Adobe and iText7 uses different methods to open the pdf file - but anyway - I can't help it tho.
Can you please help what is wrong here?
For those who wants to see the ExtractPDFDoc() method:
public static object ExtractPDFDoc(string filename)
{
iText.Kernel.Pdf.PdfReader pdfReader = null;
iText.Kernel.Pdf.PdfDocument pdfDocument = null;
try
{
pdfReader = new iText.Kernel.Pdf.PdfReader(filename);
pdfDocument = new iText.Kernel.Pdf.PdfDocument(pdfReader);
}
catch (Exception ex)
{
pdfReader = null;
pdfDocument = null;
return new Exception(string.Format("ExtractPDFDoc() failed on file '{0}' with message '{1}'", filename, ex.Message));
//this is where I get the error, ex.Message is 'Cannot open document.'
//however, I can open it in Adobe Reader but I can't delete it before closing my app.
}
}
If I remember correctly, the iText objects are all IDisposable, so you should be sure to dispose of them as well. Also, I don't know why you're returning an exception instead of just throwing it.
public static object ExtractPDFDoc(string filename)
{
iText.Kernel.Pdf.PdfReader pdfReader = null;
iText.Kernel.Pdf.PdfDocument pdfDocument = null;
try
{
pdfReader = new iText.Kernel.Pdf.PdfReader(filename);
pdfDocument = new iText.Kernel.Pdf.PdfDocument(pdfReader);
}
catch (Exception ex)
{
throw new Exception(string.Format("ExtractPDFDoc() failed on file '{0}' with message '{1}'", filename, ex.Message), ex);
}
finally
{
pdfReader?.Dispose();
pdfDocument?.Dispose();
}
}
Unrelated to that, you can also stack your using statements instead of nesting them.
using (HttpWebResponse response = (HttpWebResponse)webReq.GetResponse())
using (Stream httpResponseStream = response.GetResponseStream())
using (FileStream output = File.Create(file1))
{
// do stuff
}
I'm deeply sorry, thanks to #howcheng, I realized that it was the iText7 which leaves the file open after it's failed to open the document because of one of it's dependency files was missing in the output folder.
It's clear that I should do a .Close() on iText7 objects on exception to avoid false perceptions such as this.
Thanks for all your help.

Exception: Error getting value from 'Position' on 'Amazon.Runtime.Internal.Util.MD5Stream'

I am facing this exception
Error getting value from 'Position' on 'Amazon.Runtime.Internal.Util.MD5Stream'.
when trying to read file from aws s3 bucket.
Here is my c# code
try
{
var s3ObjectPath = $"users/{email.Id}/emailattachments/{item.AttachedFileName}";
var ifExists = await this.Exists(s3ObjectPath);
if (ifExists)
{
Stream attachment = await s3Client.GetObjectStreamAsync(attachmentS3BucketName, s3ObjectPath, dicData);
Attachment att = new Attachment(attachment, item.AttachedFileName);
attachments.Add(att);
}
}
catch (AmazonS3Exception ex)
{
}
However this is working sometimes. I searched everywhere but didn't find solution.
Thanks in advance!!
This is due to an issue with how Streams work. When you open a Stream you are not actually getting the content of the file, rather you are opening a connection enabling you to access the data.
The error you got is returned when your code is trying to access the stream but doesn't have the ability to do so (a connection being lost / no appropriate credentials in the code accessing the stream or any other reason).
The solution is either to solve the underlaying issue and make sure your code still as access to the Stream or to just read from the stream and return a string rather than a stream
The code addition would look something like this:
...
Stream attachment = await s3Client.GetObjectStreamAsync(attachmentS3BucketName, s3ObjectPath, dicData);
StreamReader reader = new StreamReader(attachment);
string attachmentText = reader.ReadToEnd();
Attachment att = new Attachment(attachmentText, item.AttachedFileName);
attachments.Add(att);

Failed to extract body due to: javax.jms.JMSException: Failed to build body from byte(Failed to extract sent Zip file to ActiveMQ)

I am trying to send message to ActiveMQ server with my client app written on C# .NET. I have XML messages which I have converted into Zip stream and trying to send.
public IMessage SendMessage(string mqUri, string brokerUri, MemoryStream message, string username, string password)
{
Uri connecturi = new Uri(mqUri);
IConnectionFactory factory = new NMSConnectionFactory(connecturi);
using (IConnection connection = factory.CreateConnection(username, password))
using (ISession session = connection.CreateSession())
{
IDestination destination = SessionUtil.GetDestination(session, brokerUri);
using (IMessageProducer producer = session.CreateProducer(destination))
{
connection.Start();
IBytesMessage request = session.CreateBytesMessage(message.ToArray());
producer.Send(request);
return request;
}
}
}
On server side when parsing data got exception like:
Execution of JMS message listener failed. Caused by: [org.apache.camel.RuntimeCamelException - Failed to extract body due to: javax.jms.JMSException: Failed to build body from bytes. Reason: java.io.StreamCorruptedException: invalid stream header: 00010000. Message: ActiveMQObjectMessage.
When I debug the code and set break point, there is exception on Bodylength and content saying 'request.Content' threw an exception of type 'Apache.NMS.MessageNotReadableException'
Is there any special zip conversion to send message on ActiveMQ server? Please Help. Thanks
The problem was converting zip to memorystream, Later I found it needs to convert .xml file to zipstream not the zip file.
public static MemoryStream CreateZipStream()
{
using (ZipFile zip = new ZipFile())
{
MemoryStream outputStream = new MemoryStream();
outputStream.Seek(0, SeekOrigin.Begin);
string filePath =
#"C:\YourXml.xml";
zip.AddFile(filePath);
zip.Save(outputStream);
return outputStream;
}
}

handling DirectoryNotFoundException errors

I offer up file downloads from my website to users. When the file exists, it works fine. But if the file is removed for whatever reason, I get the following error in Visual Studio:
An exception of type 'System.IO.DirectoryNotFoundException' occurred in
mscorlib.dll but was not handled in user code
and the users just see a JSON string on the website.
I use this offer up a stream:
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(
new FileStream(mediaFile.FilesystemLocation, FileMode.Open));
mediaFile.FilesystemLocation is simply this:
public virtual string FilesystemLocation
{
get { return Path.Combine(FilesystemRoot, Id + "." + Extension); }
}
I tried putting the whole thing in a try/catch block but then it lost all it's references to other classes.
So my question is, how can I handle this code and prevent this error?
Ideally, I'd just like to display a message to the user, "File Not Found, please contact your Administrator" or something like that.
Thanks!
System.IO.File.Exists is going to be your friend here. Before you set result.Content call this first. If the file doesn't exist, the method will return false and you can adjust your logic accordingly.
var filepath = mediaFile.FilesystemLocation;
if (!File.Exists(filepath))
{
return new HttpResponseMessage(404);
}
else{
var result = new HttpResponseMessage(HttpStatusCode.OK);
//just in case file has disappeared / or is locked for open,
//wrap in try/catch
try
{
result.Content = new StreamContent(
new FileStream(filepath, FileMode.Open));
}
catch
{
return new HttpResponseMessage(500);
}
return result;
}

Categories