dcastro's answer is good but could use some expansion:
- it doesn't take long to return
That's not quantified; let's quantify that. A property should not take more than, say, ten times longer than it would take to fetch a field.
- it doesn't connect to external resources (databases, services, etc)
Those are slow and so typically fall under the first rule, but there is a second aspect to this: failure should be rare or impossible. Property getters should not throw exceptions.
- it doesn't have any side effects
I would clarify that to observable side effects. Property getters often have the side effect that they compute the property once and cache it for later, but that's not an observable side effect.
Not only is it bad philosophically for getting a property to have an observable side effect, it can also mess up your debugging experience. Remember, when you look at an object in the debugger by default the debugger calls its property getters automatically and displays the results. If doing so is slow then that slows down debugging. If doing so can fail then your debugging experience gets full of failure messages. And if doing so has a side effect then debugging your program changes how the program works, which might make it very hard to find the bug. You can of course turn automatic property evaluation off, but it is better to design good properties in the first place.