Im trying to make a bot that sends a pm when someone joins a server, and then assigns a role based on reply to said Pm.
This is the following code i have so far for onMessageRecieved, issue is that user.getMutualGuilds() returns an empty list even though they are part of the same server as the bot.
#Override
public void onMessageReceived(MessageReceivedEvent event) {
String DmRecieved = event.getMessage().getContentRaw();
User user = event.getAuthor();
boolean isBot = user.isBot();
boolean startsWithAU = DmRecieved.toUpperCase().startsWith("AU", 0);
boolean messageTooLong = DmRecieved.length() > 8;
if (event.getMessage().getContentRaw().isEmpty()) return;
if (isBot) return;
if (!startsWithAU || messageTooLong) {
user.openPrivateChannel().queue((chanel1 ->
chanel1.sendMessage("Not valid AU ID, please try again.").queue()));
} else {
List<Guild> guilds = user.getMutualGuilds();
System.out.println(guilds);
}
}
I found the fix. The members needed to be cached in memory this was done by adding the following line to the JDA:
jda.setMemberCachePolicy(member -> true);
Related
System-Environment:
Windows 10 Pro - Version: 1909 - OS System Build: 18363.752
Microsoft Outlook 2019 MSO - Version 1808 - 32-Bit
Microsoft Exchange 2016 15.1 Build (Build 1979.3)
-- Microsoft Exchange is installed on Microsoft Server 2016
Outlook Redemption COM-Library - Version 5.22.0.5498
Issue Summary:
The application sends emails via Outlook using the Outlook-Redemption COM-Library. The class "RedemptionHandler" is our Singleton-Class which interacts with the Outlook-Redemption COM-Library. During the construction of the RedemptionHandler we create a RDOSession with a static class named RedemptionLoader and call Logon() on the RDOSession. The RDOSession is used afterwards in Initialize() to retrieve the Folders for Drafts and mails which are sent.
public static class RedemptionLoader
{
public static RDOSession new_RDOSession()
{
return (RDOSession)NewRedemptionObject(new Guid("29AB7A12-B531-450E-8F7A-EA94C2F3C05F"));
}
}
public class RedemptionHandler
{
private static RedemptionHandler instance = null;
private static readonly object padlock = new object();
private RDOSession _rdoSession;
private RDOFolder _rdoSentFolder;
private RDOFolder _rdoDraftsFolder;
private RDOItems _sentItems = null;
public EventHandler<MailGesendetEventArgs> MailSuccessfullySent;
private RedemptionHandler()
{
_rdoSession = RedemptionLoader.new_RDOSession();
_rdoSession.Logon(null, null, false, null, null, null);
Initialize();
}
public static RedemptionHandler Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new RedemptionHandler();
}
return instance;
}
}
}
private void Initialize()
{
try
{
if (isInitialized) return;
_rdoSentFolder = _rdoSession.GetDefaultFolder(Redemption.rdoDefaultFolders.olFolderSentMail);
_sentItems = _rdoSentFolder.Items;
_sentItems.ItemAdd += MailSent;
_rdoDraftsFolder = _rdoSession.GetDefaultFolder(Redemption.rdoDefaultFolders.olFolderDrafts);
isInitialized = true;
}
catch
{
//TODO
isInitialized = false;
}
}
}
At this point, we have a working instance from our RedemptionHandler. The COM-Object RDOSession is created and referenced within just as the RDOFolder for Drafts and Sent. We have also registrered an event-listener for the Sent-Folder to recognize new Mails in this folder.
In the next steps we want to send an email and recognize this email if its stored in the sent-folder. We use the RDOMail.Fields - Property to store custom data within the RDOMail-Object.
public RDOMail CreateMail(string recipient, string subject, string body, Guid gdSender, string storagePath)
{
RDOMail newMail = _rdoDraftsFolder.Items.Add(Redemption.rdoItemType.olMailItem);
newMail.Recipients.Add(recipient);
newMail.Recipients.ResolveAll();
newMail.Subject = subject;
newMail.HTMLBody = body;
newMail.BodyFormat = (int)rdoBodyFormat.olFormatHTML;
// Here we want to store an identifier in the RDOMail.Fields
int id = newMail.GetIDsFromNames(PropertyGuid, PropertyGdItemId);
newMail.Fields[id] = Guid.NewGuid().ToString();
return newMail;
}
After the mail creation we want to display the mail to the user because we dont want to send data without letting the user know about it.
public void DisplayMail(RDOMail mail, bool modal = false)
{
mail.Display(modal, null);
}
The Outlook window now comes to front and the user checks the mail and clicks on send.
The Mail is now stored in the Sent-Folder.
The MailSent Event gets invoked by the RDOFolder.Items.Add Listener.
private void MailSent(RDOMail mail)
{
var test = mail.Fields[SenderId];
Console.WriteLine(test);
// test value is correct!
}
Difference between Exchange in Online-Mode and Cache-Mode:
If we use the Exchange with Cache-Mode, everything works fine. Everytime we send an email, the MailSent is triggered and we can read data from the RDOMail.Fields-Property. If we switch to Exchange without Cache, the MailSent Event is triggered only once, when the first mail is sent. All emails afterwars are sent but dont trigger the MailSent-Event. If we delete this line of code, everything works also fine without Cache-Mode.
var test = mail.Fields[SenderId];
This is because we think that reading data from the RDOMail.Fields - Property does something special if the cache-mode from exchange is deactivated.
We need to store custom data within the mails to check if new mails in the sent-folder are created by our application or not.
We highly appreciate help and hints.
I tried to fix this issue without success. I've set-up a new Project without any other code:
public partial class RedemptionTest : Form
{
static RDOSession _rdoSession;
static RDOFolder _rdoSentFolder;
static RDOFolder _rdoDraftsFolder;
static RDOItems _draftItems;
static RDOItems _sentItems;
public RedemptionTest()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_rdoSession = RedemptionLoader.new_RDOSession();
_rdoSession.Logon();
_rdoSentFolder = _rdoSession.GetDefaultFolder(rdoDefaultFolders.olFolderSentMail);
_rdoDraftsFolder = _rdoSession.GetDefaultFolder(rdoDefaultFolders.olFolderDrafts);
_sentItems = _rdoSentFolder.Items;
_draftItems = _rdoDraftsFolder.Items;
_draftItems.ItemAdd += DraftAdd;
_sentItems.ItemAdd += MailSent;
}
private void DraftAdd(RDOMail Item)
{
Console.WriteLine(Item.Subject);
}
private void MailSent(RDOMail Item)
{
Console.WriteLine(Item.Subject);
}
}
The Drafts-Folder Event is fired all the time, the MailSent Event is only fired the first time. I have stored all RDO-Objects in static variables to avoid them from being garbage collected.
The object raising the events (RDOItems) must be alive be able to fire the events. Your code is using multiple dot notation, which means the compiler creates an implicit variable to hold the RDOItems collection. As soon as that variable is released by the Garbage Collector, no events will be fired.
The line
_rdoSentFolder.Items.ItemAdd += MailSent;
must be changed to
RDOItems _sentItems; //global/class variable
..
_sentItems = _rdoSentFolder.Items;
_sentItems .ItemAdd += MailSent;
Have the same issue in Outlook VSTO add-in using Redemption. Happens for both Sent and Inbox folder. The same code works correctly in cached mode but fires events only once in Online mode.
Native Outlook object model Items.ItemAdd works correctly in Online mode for the same folder.
Currently, we were able to do a workaround for this by unsubscribing and resubscribing to event right in the event handler. Like this:
private void SentItems_ItemAdd(RDOMail rdoMail)
{
_sentItems.ItemAdd -= SentItems_ItemAdd;
_sentItems.ItemAdd += SentItems_ItemAdd;
Log.Debug("SentItems.ItemAdd");
SentMailItemAdd?.Invoke(rdoMail);
}
I'm trying to implement Xamairn Auth with my app. I've installed the nuget package from https://www.nuget.org/packages/Xamarin.Auth.
Following their example I have the following code in the shared project.
public void SaveCredentials (string userName, string password)
{
if (!string.IsNullOrWhiteSpace (userName) && !string.IsNullOrWhiteSpace (password)) {
Account account = new Account {
Username = userName
};
account.Properties.Add ("Password", password);
AccountStore.Create ().Save (account, App.AppName);
}
}
When run on android, it saves the username and password but I'm getting the following message in the console:
"This version is insecure, because of default password.
Please use version with supplied password for AccountStore.
AccountStore.Create(Contex, string) or AccountStore.Create(string);"
I tried passing a parameter to the AccountStore.Create() method but it doesn't seem to take one. Something like this:
#if ANDROID
_accountStore = AccountStore.Create(Application.Context);
#else
_accountStore = AccountStore.Create();
#endif
Do I need to write android specific code to extend the create method.
I understand why you deleted the non-answer, I thought that would show interest in the question. I guess I should have upvoted the question instead. Anyways, here's the answer I found.
You can't use the PCL version for android. It doesn't have an option to add a password. I used the android specific version. Will call it using dependency service.
Here's an example:
Account account = null;
try
{
//account = AccountStore.Create(Application.ApplicationContext, "System.Char[]").FindAccountsForService("My APP").FirstOrDefault();
var aStore = AccountStore.Create(Application.ApplicationContext, "myownpassword");
// save test
account = aStore.FindAccountsForService(Constants.AppName).FirstOrDefault();
if (account == null)
account = new Account();
account.Username = "bobbafett";
account.Properties["pswd"] = "haha";
aStore.Save(account, Constants.AppName);
// delete test, doesn't seem to work, account is still found
var accts = aStore.FindAccountsForService(Constants.AppName);
int howMany = accts.ToList().Count;
foreach (var acct in accts)
{
aStore.Delete(acct, Constants.AppName);
}
account = aStore.FindAccountsForService(Constants.AppName).FirstOrDefault();
}
catch (Java.IO.IOException ex)
{
// This part is not invoked anymore once I use the suggested password.
int i1 = 123;
}
I was able to get it to work by implementing a getAccountStore method in android which has an option to add a password, then use DependencyService to call it.
public AccountStore GetAccountStore()
{
try
{
var acctStore = AccountStore.Create(Application.Context, "somePassword");
return acctStore;
}
catch (Java.IO.IOException ex)
{
throw ex;
}
}
Then in your pcl project call it as such:
if (Device.RuntimePlatform == Device.Android)
_accountStore = DependencyService.Get<IAccountStoreHelper>().GetAccountStore();
else
_accountStore = AccountStore.Create();
I'm using the Amazon AWS Ruby SDK for Amazon SNS but I'm having some trouble with devices already being registered. Sometimes when a device gets registered again I get an error like AWS::SNS::Errors::InvalidParameter Invalid parameter: Token Reason: Endpoint arn:aws:sns:us-east-1:**** already exists with the same Token, but different attributes.. How do I check whether an endpoint already exists and more importantly, how do I get the endpoint for a given token?
Credit to BvdBijl's idea, I made an extension method to delete the existing one if found and then add it.
using System;
using System.Text.RegularExpressions;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
namespace Amazon.SimpleNotificationService
{
public static class AmazonSimpleNotificationServiceClientExtensions
{
private const string existingEndpointRegexString = "Reason: Endpoint (.+) already exists with the same Token";
private static Regex existingEndpointRegex = new Regex(existingEndpointRegexString);
public static CreatePlatformEndpointResponse CreatePlatformEndpointIdempotent(
this AmazonSimpleNotificationServiceClient client,
CreatePlatformEndpointRequest request)
{
try
{
var result = client.CreatePlatformEndpoint(request);
return result;
}
catch (AmazonSimpleNotificationServiceException e)
{
if (e.ErrorCode == "InvalidParameter")
{
var match = existingEndpointRegex.Match(e.Message);
if (match.Success) {
string arn = match.Groups[1].Value;
client.DeleteEndpoint(new DeleteEndpointRequest
{
EndpointArn = arn,
});
return client.CreatePlatformEndpoint(request);
}
}
throw;
}
}
}
}
It looks like amazone resolved this issue.
I'm using RoR and used to have same problem when trying to register and existing GCM code I got an error message saying
"AWS::SNS::Errors::InvalidParameter Invalid parameter: Token Reason: Endpoint arn:aws:sns:us-east-1:**** already exists with the same Token, but different attributes."
although I used same (empty) attributes. Now when I send an existing GCM code (with same attributes as the original one) I get the endpoint arn and not the error message.
ListEndpointsByPlatformApplication only return 100 endpoints, you have to use nextToken to get more. Here is my implementation.
public void deleteEndpoint(string token, string PlatformApplicationArn)
{
ListEndpointsByPlatformApplicationRequest listRequest = new ListEndpointsByPlatformApplicationRequest();
listRequest.PlatformApplicationArn = PlatformApplicationArn;
Logger.Info("Deleting endpoint with token -> " + token);
var list = snsClient.ListEndpointsByPlatformApplication(listRequest);
do
{
foreach (var x in list.Endpoints.Where(x => x.Attributes["Token"] == token))
{
snsClient.DeleteEndpoint(new DeleteEndpointRequest() { EndpointArn = x.EndpointArn });
Logger.Info("Endpoint removed-> " + x.EndpointArn);
return;
}
listRequest.NextToken = list.NextToken;
list = snsClient.ListEndpointsByPlatformApplication(listRequest);
}
while (list.NextToken != null);
}
Welcome!
I have a little problem with own application. This app can be connect(sith socket) an FTP server, and its work fine. But my problem is, if the user use bad usernam or password, the program won't receive the response statucode. Whats wrong?
I would like to use this statuscode some clause to examine(usernem or/and password etc.)
Code:
public static void ReadResponse()
{
result = ParseHostResponse();
statusCode = int.Parse(result.Substring(0, 3));
statusMessage = "";
}
The ParseHostResponse() method contains next:
Code:
public static string ParseHostResponse()
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = socket.RemoteEndPoint;
socketEventArg.SetBuffer(buffer, BUFFER_SIZE, 0);
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
statusMessage = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
statusMessage = statusMessage.Trim('\0');
}
else
{
statusMessage = e.SocketError.ToString();
}
});
socket.ReceiveAsync(socketEventArg);
string[] msg = statusMessage.Split('\n');
if (statusMessage.Length > 2)
{
statusMessage = msg[msg.Length - 2];
}
else
{
statusMessage = msg[0];
}
if (!statusMessage.Substring(3, 1).Equals(" "))
{
return ParseHostResponse();
}
return statusMessage;
}
If I invite to the ReadResponse() method, the Visual Studio answer with this exception: NullReferenceException
in this code:
Code:
.
.
string[] msg = statusMessage.Split('\n');
.
What is the wrong? This code issue to http://msdn.microsoft.com/en-us/library/hh202858%28v=vs.92%29.aspx#BKMK_RECEIVING
Thank you for your help!
I can't help, but have to start with these side remarks:
statusMessage.Trim('\0') does not work (try it)
statusMessage.Split('\n') is inefficient as it involves extra allocations (guess why)
Now to the actual subject: I never used sockets on WP7, but from what I know about async operations it looks to me that you start async op (by calling ReceiveAsync) and use the result (statusMessage) before the answer arrives.
Think a bit about your design of the ParseHostResponse() method:
Bad name: Indicates parsing of a response, while it actually performs communication
Bad functionality: The method indicates sync patter, but internally uses async pattern. I don't know what to suggest here as every solution seems to be wrong. For example waiting for a response will make UI irresposible.
My main recommendation is that you get more information about async programming and then reprogramm your app accordingly.
I need to send hundreds of newsletters, but would like to check first if email exists on server. It's called SMTP validation, at least I think so, based on my research on Internet.
There's several libraries that can do that, and also a page with open-source code in ASP Classic (http://www.coveryourasp.com/ValidateEmail.asp#Result3), but I have hard time reading ASP Classic, and it seems that it uses some third-party library...
Is there some code for SMTP validation in C#, and/or general explanation of how it works?
Be aware that most MTAs (Mail Transfer Agent) will have the VRFY command turned off for spam protection reasons, they'll probably even block you if you try several RCPT TO in a row (see http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html). So even if you find a library to do that verification, it won't be worth a lot. Ishmaeel is right, the only way to really find out, is sending an email and see if it bounces or not.
#Hrvoje: Yes, I'm suggesting you monitor rejected emails. BUT: not all the bounced mails should automatically end up on your "does not exist"-list, you also have to differentiate between temporary (e.g. mailbox full) and permanent errors.
SMTP is a text based protocol carried over TCP/IP.
Your validation program needs to open a TCP/IP connection to the server's port 25 (SMTP), write in a few lines and read the answer. Validation is done (but not always) on the "RCTP TO" line and on the "VFRY" line.
The SMTP RFC describes how this works (see Green#Beta.ARPA below, S are lines sent by the client, R are lines received from the server):
Example of the SMTP Procedure
This SMTP example shows mail sent by Smith at host Alpha.ARPA,
to Jones, Green, and Brown at host Beta.ARPA. Here we assume
that host Alpha contacts host Beta directly.
S: MAIL FROM:
R: 250 OK
S: RCPT TO:
R: 250 OK
S: RCPT TO:
R: 550 No such user here
While it's true that many domains will return false positives because of abuse, there are still some great components out there that will perform several levels of validation beyond just the SMTP validation. For example, it's worth it to check first to see if at least the domain exists. I'm in the process of compiling my own list of resources related to this question which you can track here:
http://delicious.com/dworthley/email.validation (broken link)
For those who might want to add to this list, I'll also include what I currently have here:
aspNetMX
.NET Email Validation Wizard Class Library
MONOProg Email Validator.Net
For a bulletproof form and a great user experience, it's helpful to validate as many aspects of the email address as possible. I can see from the aspNetMX validator that they check:
the syntax
the email against a list of bad email addresses
the domain against a list of bad domains
a list of mailbox domains
whether or not the domain exists
whether there are MX records for the domain
and finally through SMTP whether or not a mailbox exists
It's this last step that can be circumvented by administrators by returning true to basically all account verification requests, but in most cases if the user has intentionally entered a bad address it's already been caught. And if it was user error in the domain part of the address, that will be caught too.
Of course, a best practice for using this kind of a service for a registration screen or form would be to combine this kind of validation with a verification process to ensure that the email address is valid. The great thing about using an email validator in front of a verification process is that it will make for a better overall user experience.
You can try the below code, it works fine for me :
public class EmailTest {
private static int hear(BufferedReader in) throws IOException {
String line = null;
int res = 0;
while ((line = in.readLine()) != null) {
String pfx = line.substring(0, 3);
try {
res = Integer.parseInt(pfx);
} catch (Exception ex) {
res = -1;
}
if (line.charAt(3) != '-')
break;
}
return res;
}
private static void say(BufferedWriter wr, String text) throws IOException {
wr.write(text + "\r\n");
wr.flush();
return;
}
#SuppressWarnings({ "rawtypes", "unchecked" })
private static ArrayList getMX(String hostName) throws NamingException {
// Perform a DNS lookup for MX records in the domain
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext(env);
Attributes attrs = ictx.getAttributes(hostName, new String[] { "MX" });
Attribute attr = attrs.get("MX");
// if we don't have an MX record, try the machine itself
if ((attr == null) || (attr.size() == 0)) {
attrs = ictx.getAttributes(hostName, new String[] { "A" });
attr = attrs.get("A");
if (attr == null)
throw new NamingException("No match for name '" + hostName + "'");
}
/*
Huzzah! we have machines to try. Return them as an array list
NOTE: We SHOULD take the preference into account to be absolutely
correct. This is left as an exercise for anyone who cares.
*/
ArrayList res = new ArrayList();
NamingEnumeration en = attr.getAll();
while (en.hasMore()) {
String mailhost;
String x = (String) en.next();
String f[] = x.split(" ");
// THE fix *************
if (f.length == 1)
mailhost = f[0];
else if (f[1].endsWith("."))
mailhost = f[1].substring(0, (f[1].length() - 1));
else
mailhost = f[1];
// THE fix *************
res.add(mailhost);
}
return res;
}
#SuppressWarnings("rawtypes")
public static boolean isAddressValid(String address) {
// Find the separator for the domain name
int pos = address.indexOf('#');
// If the address does not contain an '#', it's not valid
if (pos == -1)
return false;
// Isolate the domain/machine name and get a list of mail exchangers
String domain = address.substring(++pos);
ArrayList mxList = null;
try {
mxList = getMX(domain);
} catch (NamingException ex) {
return false;
}
/*
Just because we can send mail to the domain, doesn't mean that the
address is valid, but if we can't, it's a sure sign that it isn't
*/
if (mxList.size() == 0)
return false;
/*
Now, do the SMTP validation, try each mail exchanger until we get
a positive acceptance. It *MAY* be possible for one MX to allow
a message [store and forwarder for example] and another [like
the actual mail server] to reject it. This is why we REALLY ought
to take the preference into account.
*/
for (int mx = 0; mx < mxList.size(); mx++) {
boolean valid = false;
try {
int res;
//
Socket skt = new Socket((String) mxList.get(mx), 25);
BufferedReader rdr = new BufferedReader(new InputStreamReader(skt.getInputStream()));
BufferedWriter wtr = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));
res = hear(rdr);
if (res != 220)
throw new Exception("Invalid header");
say(wtr, "EHLO rgagnon.com");
res = hear(rdr);
if (res != 250)
throw new Exception("Not ESMTP");
// validate the sender address
say(wtr, "MAIL FROM: <tim#orbaker.com>");
res = hear(rdr);
if (res != 250)
throw new Exception("Sender rejected");
say(wtr, "RCPT TO: <" + address + ">");
res = hear(rdr);
// be polite
say(wtr, "RSET");
hear(rdr);
say(wtr, "QUIT");
hear(rdr);
if (res != 250)
throw new Exception("Address is not valid!");
valid = true;
rdr.close();
wtr.close();
skt.close();
} catch (Exception ex) {
// Do nothing but try next host
ex.printStackTrace();
} finally {
if (valid)
return true;
}
}
return false;
}
public static void main(String args[]) {
String testData[] = { "rahul.saraswat#techblue.com", "rahul.saraswat#techblue.co.uk", "srswt.rahul12345#gmail.com",
"srswt.rahul#gmail.com" };
System.out.println(testData.length);
for (int ctr = 0; ctr < testData.length; ctr++) {
System.out.println(testData[ctr] + " is valid? " + isAddressValid(testData[ctr]));
}
return;
}
}
Thanks & Regards
Rahul Saraswat
The Real(TM) e-mail validation is trying to send something to the address, and seeing if it is rejected/bounced. So, you'll just have to send them away, and remove the addresses that fail from your mailing list.
Don't take this the wrong way, but sending newsletters to more than a handful of people these days is a fairly serious matter. Yes, you need to be monitoring bounces (rejected emails) which can occur synchronously during the SMTP send (typically if the SMTP server you are connected to is authoritative), or asynchronously as a system-generated email message that occurs some amount of time after the SMTP send succeeded.
Also keep the CAN-SPAM Act in mind and abide by the law when sending these emails; you've got to provide an unsub link as well as a physical street address (to both identify you and t0 allow users to send unsub requests via snail-mail if they so choose).
Failure to do these things could get your IP null-routed at best and sued at worst.
You may need this Email Validator component for .NET
Here is the code example:
// Create a new instance of the EmailValidator class.
EmailValidator em = new EmailValidator();
em.MessageLogging += em_MessageLogging;
em.EmailValidated += em_EmailValidationCompleted;
try
{
string[] list = new string[3] { "test1#testdomain.com", "test2#testdomain.com", "test3#testdomain.com" };
em.ValidateEmails(list);
}
catch (EmailValidatorException exc2)
{
Console.WriteLine("EmailValidatorException: " + exc2.Message);
}