I need your help in finding better way in downloading a url using HttpWebResponse
I used next code
HttpWebResponse myboot = HttpWebRequest.Create("http://www.wwenews.us/m1.php?id=441229").GetResponse() as HttpWebResponse;
StreamReader myboot_content = new StreamReader(myboot.GetResponseStream(), Encoding.GetEncoding("windows-1256"));
string temp_data = myboot_content.ReadToEnd();
but a problem says
The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF
appears to me when trying parsing http://www.wwenews.us/m1.php?id=441229
please help me to download string of this site
note: test your solution code before present it as I had tested several solutions and no one solve the problem
Add a reference to System.Configuration to your project and add the following method.
public static bool SetUnsafeHeaderParsing()
{
Assembly oAssembly = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection));
if (oAssembly != null)
{
Type oAssemblyType = oAssembly.GetType("System.Net.Configuration.SettingsSectionInternal");
if (oAssemblyType != null)
{
object oInstance = oAssemblyType.InvokeMember("Section",
BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { });
if (oInstance != null)
{
FieldInfo objFeild = oAssemblyType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance);
if (objFeild != null)
{
objFeild.SetValue(oInstance, true);
return true;
}
}
}
}
return false;
}
Call the method SetUnsafeHeaderParsing() before you use the HttpWebRequest.Create method call.
Its actually a problem with the server. The server is not following the HTTP specifications. However your .NET client by default would adhere to the specs and flags it as a potential problem.
Skype installed on the same machine as the web server can cause such problems, as it's using the same port (80) by default.
To change that port look here:
http://forum.skype.com/index.php?showtopic=31024
Related
I am trying to follow the approach suggested in a post by Allan Eagle in code-project. This same approach was working fine up until .NET Core 3.1, but not with .NET 5.0 . Here is the save method I created,
private void Save(MailMessage message, string filePath)
{
var assembly = typeof(SmtpClient).Assembly;
var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
var mailWriterContructor = mailWriterType.GetConstructors(bindingFlags)[0];
var mailWriter = mailWriterContructor.Invoke(new object[] { fileStream });//<-- This line throws error saying parameter mismatch
var sendMethod = typeof(MailMessage).GetMethod("Send", bindingFlags);
sendMethod.Invoke(message, bindingFlags, null, new[] { mailWriter, true, true }, null);
var closeMethod = mailWriter.GetType().GetMethod("Close", bindingFlags);
closeMethod.Invoke(mailWriter, bindingFlags, null, new object[] { }, null);
}
}
I checked all the available underlying invoke methods and tried working with them passing needed parameters but non of them worked for me.
Error Message: "Parameter count mismatch."
Inner Exception: null
Stack Trace:
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
at..//user written line info
Any help to solve this issue or new approach to achieve same thing using System.Net.Mail will be highly appreciated.
To explicitly give you an answer based on first comment,
var encodeForTransport = false;
var mailWriter = mailWriterContructor.Invoke(new object[] { fileStream, encodeForTransport });
As I mentioned in the comments, this article is obsolete in 2020. Despite the date, it was actually written in 2009 and stopped working in 2014, when some of the internal methods changed signature. In any case, the System.Net.Mail namespace shouldn't be used because, as Microsoft strongly warns:
Important
We don't recommend that you use the SmtpClient class for new development because SmtpClient doesn't support many modern protocols. Use MailKit or other libraries instead. For more information, see SmtpClient shouldn't be used on GitHub.
MailKit (or rather the MimeKit library it's built upon) already supports saving and loading Mail messages. From Q: How do I save messages? the answer is a simple:
message.WriteTo("message.eml");
You can use MailKit's POP3 or IMAP4 clients to retrieve messages. The DownloadMessages example show how to download messages from GMail and save them:
using (var client = new Pop3Client (new ProtocolLogger ("pop3.log"))) {
client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect);
client.Authenticate ("username", "password");
for (int i = 0; i < client.Count; i++) {
var message = client.GetMessage (i);
// write the message to a file
message.WriteTo (string.Format ("{0}.msg", i));
// mark the message for deletion
client.DeleteMessage (i);
}
client.Disconnect (true);
}
I'm trying to upload file to Sharepoint 2013 using web service copy.asmx
I've created simple project with the following method:
public bool UploadFile(string file, string destination)
{
bool success = false;
CopySoapClient client = new CopySoapClient();
if (client.ClientCredentials != null)
{
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("admin", "password", "domain");
}
try
{
client.Open();
string filename = Path.GetFileName(file);
string destinationUrl = destination +#"/"+ filename;
string[] destinationUrls = { destination };
FieldInformation i1 = new FieldInformation { DisplayName = "Title", InternalName = "Title", Type = FieldType.Text, Value = filename};
FieldInformation[] info = { i1 };
CopyResult[] result;
byte[] data = File.ReadAllBytes(file);
uint ret = client.CopyIntoItems(file, destinationUrls, info, data, out result);
if (result != null && result.Length > 0 && result[0].ErrorCode == 0)
success = true;
}
finally
{
if (client.State == System.ServiceModel.CommunicationState.Faulted)
client.Abort();
if (client.State != System.ServiceModel.CommunicationState.Closed)
client.Close();
}
return success;
}
CopySoapClient is part Copy service reference
http://SPSITE/_vti_bin/copy.asmx
The method is called using following parameters:
UploadFile(#"C:\temp\test.txt", "http://SPSITE/sites/Connector/documents/test.txt");
The problem is, when program executes
uint ret = client.CopyIntoItems(file, destinationUrls, info, data, out result);
the web service returns in result "Unknown error" with description "Object reference not set to an instance of an object."
I really don't know what I'm missing. Can anyone help me out?
Thank you.
P.S. I've noticed in examples provided on the Internet that people are using a Copy class from copy.asmx. But I only have CopySoapClient class.
you used the right web services but on wrong SharePoint site. Try to make this web services reference on the same sharepoint site you have posted here as target library.
missing the OPTIONAL element of <Fields> and <FieldInformation >, resulted ErrorCode="Unknown" ErrorMessage="Object reference not set to an instance of an object." . even though, Field and FieldInformation supposed to be optional. It could be the server side configuration. Anyway, it works for me now, adding all attributed, required/optional.
I'm currently looking at serializing a MailMessage object in C# and although there are a couple of variations of an example on the net, they serialize to binary which kind of misses the point IMO.
My approach is that I'd like to serialize a MailMessage to an RFC2822 eml string and the code below is what I've come up with.
public string SerializeEmail(MailMessageArgs e)
{
string rfc822eml = "";
Guid g = Guid.NewGuid();
lock (g.ToString())
{
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(#"C:\tmpspool");
di.CreateSubdirectory(g.ToString());
string spoolDir = #"C:\tmpspool\" + g.ToString();
SmtpClient Client = new SmtpClient("localhost");
Client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
Client.PickupDirectoryLocation = spoolDir;
Client.Send(e.mailObj);
var files = from file in Directory.EnumerateFiles(spoolDir)
select file;
string serializedEml = files.First();
rfc822eml = File.ReadAllText(serializedEml);
File.Delete(serializedEml);
Directory.Delete(spoolDir);
}
return rfc822eml;
}
It's pretty nasty but it does work. Ideally though, I'd create a new SMTPClient and add in a Serialize function which would return the rfc822 string automatically without it ever hitting the file system.
As I don't seem to be able to trace into the SMTPClient.Send function with Visual Studio, this "ideal" way of doing things is a tad tricky.
I've already sorted out the deserialization of the RFC message by adding in some small changes to Peter Huber's POP3MimeClient and POP3MailClient classes so I can deserialize a file on the HDD or a string back into a MailMessage.
The thing that's nagging at me is that I really should be able to serialize the MailMessaage using a stream and writing the stream to a string -or- file of my choice instead of going around the houses to create GUID based folders as the code above does and reading the content of the file back into a string...
Any pointers as to how I could make this more elegant will be much appreciated.
Thanks.
This will be a hack. Don't forget, MS can change it in the next versions of .Net.
(With the help of ILSpy) you can write an extension method like below
public static class MailExtensions
{
public static string ToEml(this MailMessage mail)
{
var stream = new MemoryStream();
var mailWriterType = mail.GetType().Assembly.GetType("System.Net.Mail.MailWriter");
var mailWriter = Activator.CreateInstance(
type: mailWriterType,
bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic,
binder: null,
args: new object[] { stream },
culture: null,
activationAttributes: null);
mail.GetType().InvokeMember(
name: "Send",
invokeAttr: BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
binder: null,
target: mail,
args: new object[] { mailWriter, true, true });
return Encoding.UTF8.GetString(stream.ToArray());
}
}
and use as
string eml = mailMessage.ToEml();
I finally managed to deserialize the MailMessage after a lot of work:
To get it right, I created a dll which will be used in both the client application and the webservice. This needs to be the same for the deserialization to work :)
I picked the dll serialization classes here: https://bitbucket.org/burningice/compositec1contrib.email/src/0bba07df532c8134717cfb40757f4cb22f002b1d/Email/Serialization/?at=default
Many thanks for sharing!
Once compiled and added my new dll to the projects, the send and receive worked.
So I convert the MailMessage this way : string serializedMessage = SerializeAsBase64(mail);
and in the Webservice, I reconstruct it this way :
MailMessage Mm = DeserializeFromBase64(serializedMessage);
I hope this helps...
I try to get the content ID's of the attachments of mails in outlook. I use Add-In Express for my Add-In, but it has no function to get it.
I know of the Redemption library, but it's not free and thus not an option for me.
In Outlook 2007+ there is the PropertyAccessor, which should me allow to do it, but I can't get it to work.
Here my code:
string uniqueId = "";
object props = a.GetType().InvokeMember("PropertyAccessor", BindingFlags.Public | BindingFlags.GetField | BindingFlags.GetProperty, null, a, null);
object[] args = new object[1];
args[0] = #"urn:schemas:mailheader:content-id";
object value = props.GetType().InvokeMember("GetProperty", BindingFlags.Public | BindingFlags.InvokeMethod, null, props, args);
if ((string)value != null) {
uniqueId = (string)value;
}
"a" is an attachment gotten from an Add-In Express MailItem.
It just throws the following exception: "Exception has been thrown by the target of an invocation."
Can someone help me?
I tried your URN as well and it did not work.
Using DASL, this works: http://schemas.microsoft.com/mapi/proptag/0x3712001F
Outlook Spy has a free trial period. I would download that in the meantime (which is where I found this value). And even when it expires, this valuable tool is less than Redemption itself.
I need to request the following URL inside my application:
http://feedbooks.com/type/Crime%2FMystery/books/top
When I run the following code:
Uri myUri = new Uri("http://feedbooks.com/type/Crime%2FMystery/books/top");
The Uri constructor decodes the %2F into a literal /, and I get a 404 error because it has changed the URL to:
http://feedbooks.com/type/Crime/Mystery/books/top
The Uri class has a constructor that takes a parameter dontEscape, but that constructor is deprecated and setting it to true has no effect.
My first thought was to do something like:
Uri myUri = new Uri("http://feedbooks.com/type/Crime%252FMystery/books/top");
With the hopes that it would convert %25 into a literal %, but that didn't work either.
Any ideas how to create a correct Uri object for this particular URL in .NET?
It's a bit easier in .NET 4.0. You can put a setting in your config file like this:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
It only works for the 'http' and 'https' schemes.
Or here's a new version of the LeaveDotsAndSlashesEscaped method. It doesn't need a particular Uri instance, just call it when your application starts up:
private void LeaveDotsAndSlashesEscaped()
{
var getSyntaxMethod =
typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
if (getSyntaxMethod == null)
{
throw new MissingMethodException("UriParser", "GetSyntax");
}
var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
var setUpdatableFlagsMethod =
uriParser.GetType().GetMethod("SetUpdatableFlags", BindingFlags.Instance | BindingFlags.NonPublic);
if (setUpdatableFlagsMethod == null)
{
throw new MissingMethodException("UriParser", "SetUpdatableFlags");
}
setUpdatableFlagsMethod.Invoke(uriParser, new object[] {0});
}
I ran into the same problem using 2.0...
I discovered a workaround posted at this blog:
// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
private const int UnEscapeDotsAndSlashes = 0x2000000;
public static void LeaveDotsAndSlashesEscaped(Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
FieldInfo fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null)
{
throw new MissingFieldException("'m_Syntax' field not found");
}
object uriParser = fieldInfo.GetValue(uri);
fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null)
{
throw new MissingFieldException("'m_Flags' field not found");
}
object uriSyntaxFlags = fieldInfo.GetValue(uriParser);
// Clear the flag that we don't want
uriSyntaxFlags = (int)uriSyntaxFlags & ~UnEscapeDotsAndSlashes;
fieldInfo.SetValue(uriParser, uriSyntaxFlags);
}
It works perfectly.
Hope this helps (better late than never!)
This is a bug I filed a while back. It's supposed to be fixed in 4.0, but I'm not holding my breath. Apparently it's still a problem in the RC.
By combining the 2 previous answers you can have a method you only need to call once per process that works both on .net 4 and .net 3.5.
// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
private const int UnEscapeDotsAndSlashes = 0x2000000;
private void LeaveDotsAndSlashesEscaped()
{
var getSyntaxMethod =
typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
if (getSyntaxMethod == null)
{
throw new MissingMethodException("UriParser", "GetSyntax");
}
var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
FieldInfo flagsFieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.Instance);
if (flagsFieldInfo == null)
{
throw new MissingFieldException("UriParser", "m_Flags");
}
int flags = (int) flagsFieldInfo.GetValue(uriParser);
// unset UnEscapeDotsAndSlashes flag and leave the others untouched
flags = flags & ~UnEscapeDotsAndSlashes;
flagsFieldInfo.SetValue(uriParser, flags);
}